Utilities.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Installer *
  23. * *
  24. * $Archive:: /Commando/Code/Installer/Utilities.cpp $*
  25. * *
  26. * $Author:: Ian_l $*
  27. * *
  28. * $Modtime:: 1/11/02 10:27a $*
  29. * *
  30. * $Revision:: 10 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. // Includes.
  36. #include "Utilities.h"
  37. #include "ErrorHandler.h"
  38. #include "Resource.h"
  39. #include "Translator.h"
  40. #include <shlwapi.h>
  41. #include <stdlib.h>
  42. #include <winbase.h>
  43. #include <shlobj.h>
  44. // Private prototypes.
  45. static bool Create_Directory (const WCHAR *drive, const WCHAR *directory, WCHAR *subdirectory, bool remove, DynamicVectorClass <StringClass> *log);
  46. static WCHAR *Standardize_Path (const WideStringClass &path, WideStringClass &standardpath);
  47. static bool Validate_Install_CD (const char driveletter, const WideStringClass &installvolumename);
  48. /***********************************************************************************************
  49. * Prompt_Install_CD -- Is the install CD in one of the CD drives? If not prompt for it. *
  50. * *
  51. * INPUT: *
  52. * *
  53. * OUTPUT: *
  54. * *
  55. * WARNINGS: *
  56. * *
  57. * HISTORY: *
  58. * 08/22/01 IML : Created. *
  59. *=============================================================================================*/
  60. bool Prompt_Install_CD (const WideStringClass &installvolumename, char &sourcedriveletter)
  61. {
  62. bool success = false;
  63. while (!success) {
  64. for (char r = 'A'; r <= 'Z'; r++) {
  65. char rootpathname [] = "?:\\";
  66. rootpathname [0] = r;
  67. // If the drive is a CD-ROM...
  68. if (GetDriveType (rootpathname) == DRIVE_CDROM) {
  69. if (Validate_Install_CD (r, installvolumename)) {
  70. sourcedriveletter = r;
  71. success = true;
  72. break;
  73. }
  74. }
  75. }
  76. if (!success) {
  77. bool cancel;
  78. // No CD-ROM with the correct label found. Ask user to insert the CD-ROM.
  79. ShowCursor (true);
  80. cancel = MessageBoxExW (NULL, TxWideStringClass (IDS_INSERT_GAME_CD_ROM), TxWideStringClass (IDS_APPLICATION_NAME), MB_RETRYCANCEL | MB_APPLMODAL | MB_SETFOREGROUND, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT)) == IDCANCEL;
  81. ShowCursor (false);
  82. if (cancel) break;
  83. }
  84. }
  85. return (success);
  86. }
  87. /***********************************************************************************************
  88. * Validate_Install_CD -- Is the install CD in the designated CD drive? *
  89. * *
  90. * INPUT: *
  91. * *
  92. * OUTPUT: *
  93. * *
  94. * WARNINGS: *
  95. * *
  96. * HISTORY: *
  97. * 08/22/01 IML : Created. *
  98. *=============================================================================================*/
  99. bool Validate_Install_CD (const WideStringClass &sourcepath, const WideStringClass &installvolumename)
  100. {
  101. StringClass multibytesourcepath (sourcepath);
  102. return (Validate_Install_CD (multibytesourcepath [0], installvolumename));
  103. }
  104. /***********************************************************************************************
  105. * Validate_Install_CD -- Is the install CD in the designated CD drive? *
  106. * *
  107. * INPUT: *
  108. * *
  109. * OUTPUT: *
  110. * *
  111. * WARNINGS: *
  112. * *
  113. * HISTORY: *
  114. * 08/22/01 IML : Created. *
  115. *=============================================================================================*/
  116. bool Validate_Install_CD (const char driveletter, const WideStringClass &installvolumename)
  117. {
  118. char multibytevolumename [_MAX_PATH];
  119. char filesystemname [_MAX_PATH];
  120. DWORD maxfilenamelength;
  121. DWORD flags;
  122. char rootpathname [] = "?:\\";
  123. rootpathname [0] = driveletter;
  124. if (GetVolumeInformation (rootpathname, multibytevolumename, _MAX_PATH, NULL, &maxfilenamelength, &flags, filesystemname, _MAX_PATH)) {
  125. WideStringClass volumename (multibytevolumename);
  126. // Windows '95 appears to have a volume name limit of 11 characters. I cannot find a Win32
  127. // call that will return the maximum volume name length so the value '11' is hard-coded here
  128. // and the assumption made that all OS's have this length or better.
  129. if (wcsncmp (volumename, installvolumename, MAX (11, volumename.Get_Length())) == 0) {
  130. return (true);
  131. }
  132. }
  133. return (false);
  134. }
  135. /***********************************************************************************************
  136. * Get_Disk_Space_Available -- *
  137. * *
  138. * INPUT: *
  139. * *
  140. * OUTPUT: *
  141. * *
  142. * WARNINGS: *
  143. * *
  144. * HISTORY: *
  145. * 08/22/01 IML : Created. *
  146. *=============================================================================================*/
  147. bool Get_Disk_Space_Available (const WideStringClass &path, __int64 &diskspace)
  148. {
  149. StringClass multibytepath (path);
  150. char drive [_MAX_DRIVE];
  151. ULARGE_INTEGER freebytecount; // Free bytes on disk available to caller (caller may not have access to entire disk).
  152. ULARGE_INTEGER totalbytecount; // Total bytes on disk.
  153. StringClass kernelpathname;
  154. int (__stdcall *getfreediskspaceex) (LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
  155. // Extract the drive.
  156. // NOTE 0: Even though GetDiskFreeSpaceEx() will accept a full path, it will err if the path is not valid.
  157. // NOTE 1: _splitpath() automatically handles multi-byte character strings.
  158. _splitpath (multibytepath, drive, NULL, NULL, NULL);
  159. GetSystemDirectory (kernelpathname.Get_Buffer (_MAX_PATH), _MAX_PATH);
  160. kernelpathname += "\\";
  161. kernelpathname += "Kernel32.dll";
  162. getfreediskspaceex = (int (_stdcall*) (LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)) GetProcAddress (GetModuleHandle (kernelpathname.Peek_Buffer()), "GetDiskFreeSpaceExA");
  163. if (getfreediskspaceex != NULL) {
  164. // NOTE: This function uses GetDiskFreeSpaceEx() and therefore assumes Win '95 OSR2 or greater.
  165. if (!getfreediskspaceex (drive, &freebytecount, &totalbytecount, NULL)) return (false);
  166. // Convert to a 64-bit integer.
  167. diskspace = freebytecount.QuadPart;
  168. } else {
  169. DWORD sectorspercluster, bytespersector, freeclustercount, totalclustercount;
  170. // The Ex version is not available. Use the Win'95 version.
  171. // QUESTION: SDK docs say that values returned by this function are erroneous if partition > 2Gb.
  172. // Does that mean that the partition is guaranteed to be <= 2Gb if Ex is not available?
  173. if (!GetDiskFreeSpace (drive, &sectorspercluster, &bytespersector, &freeclustercount, &totalclustercount)) return (false);
  174. diskspace = sectorspercluster * bytespersector * freeclustercount;
  175. }
  176. return (true);
  177. }
  178. /***********************************************************************************************
  179. * Validate_Path -- *
  180. * *
  181. * INPUT: *
  182. * *
  183. * OUTPUT: *
  184. * *
  185. * WARNINGS: *
  186. * *
  187. * HISTORY: *
  188. * 08/22/01 IML : Created. *
  189. *=============================================================================================*/
  190. bool Validate_Path (const WideStringClass &path, int &errorcode)
  191. {
  192. bool valid = false;
  193. // Check that path has syntax <drive>:\<directory>\<directory>...
  194. if (path.Get_Length() > _MAX_DRIVE) {
  195. if (((path [0] >= L'A') && (path [0] <= L'Z')) || ((path [0] >= L'a') && (path [0] <= L'z'))) {
  196. if ((path [1] == L':') && ((path [2] == L'\\') || (path [2] == L'/'))) {
  197. const WCHAR *c = ((WideStringClass) path).Peek_Buffer() + _MAX_DRIVE;
  198. while (*c != L'\0') {
  199. if ((*c == L'\\') || (*c == L'/')) {
  200. // Cannot have two adjacent slashes.
  201. if ((*(c - 1) == L'\\') || (*(c - 1) == L'/')) break;
  202. }
  203. c++;
  204. }
  205. // Parsed entire string?
  206. if (*c == L'\0') {
  207. // Check that path does not contain any illegal characters.
  208. if (wcscspn (((WideStringClass) path).Peek_Buffer(), L"*?<>|") == (size_t) path.Get_Length()) {
  209. WCHAR drive [_MAX_DRIVE + 1];
  210. WideStringClass directory;
  211. wcsncpy (drive, path, _MAX_DRIVE);
  212. drive [_MAX_DRIVE] = L'\0';
  213. directory = ((WideStringClass) path).Peek_Buffer() + _MAX_DRIVE;
  214. // Attempt to create (and then remove) the path.
  215. if (Create_Directory (drive, directory.Peek_Buffer(), directory.Peek_Buffer(), true, NULL)) {
  216. valid = true;
  217. } else {
  218. errorcode = IDS_CANNOT_CREATE_DIRECTORY;
  219. }
  220. } else {
  221. errorcode = IDS_INVALID_PATH;
  222. }
  223. } else {
  224. errorcode = IDS_INVALID_PATH;
  225. }
  226. } else {
  227. errorcode = IDS_INVALID_PATH;
  228. }
  229. } else {
  230. errorcode = IDS_INVALID_PATH;
  231. }
  232. } else {
  233. errorcode = IDS_INVALID_PATH;
  234. }
  235. return (valid);
  236. }
  237. /***********************************************************************************************
  238. * Create_Directory -- *
  239. * *
  240. * INPUT: *
  241. * *
  242. * OUTPUT: *
  243. * *
  244. * WARNINGS: *
  245. * *
  246. * HISTORY: *
  247. * 08/22/01 IML : Created. *
  248. *=============================================================================================*/
  249. bool Create_Directory (const WideStringClass &path, DynamicVectorClass <StringClass> *log)
  250. {
  251. WCHAR drive [_MAX_DRIVE + 1];
  252. WideStringClass directory;
  253. // NOTE: Assumes that path is a full path. If not, an error may be thrown.
  254. wcsncpy (drive, path, _MAX_DRIVE);
  255. drive [_MAX_DRIVE] = L'\0';
  256. directory = ((WideStringClass) path).Peek_Buffer() + _MAX_DRIVE;
  257. return (Create_Directory (drive, directory.Peek_Buffer(), directory.Peek_Buffer(), false, log));
  258. }
  259. /***********************************************************************************************
  260. * Create_Directory -- *
  261. * *
  262. * INPUT: *
  263. * *
  264. * OUTPUT: *
  265. * *
  266. * WARNINGS: *
  267. * *
  268. * HISTORY: *
  269. * 08/22/01 IML : Created. *
  270. *=============================================================================================*/
  271. bool Create_Directory (const WCHAR *drive, const WCHAR *directory, WCHAR *subdirectory, bool remove, DynamicVectorClass <StringClass> *log)
  272. {
  273. bool valid;
  274. WCHAR *c, replacement;
  275. WideStringClass path;
  276. StringClass multibytepath;
  277. DWORD errorcode;
  278. // If subdirectory is empty, we're done.
  279. c = subdirectory;
  280. if (*c != L'\0') {
  281. // Step down the subdirectory to the next slash or null.
  282. while ((*c != L'\\') && (*c != L'/') && (*c != L'\0')) c++;
  283. replacement = *c;
  284. *c = L'\0';
  285. path = drive;
  286. path += directory;
  287. path.Convert_To (multibytepath);
  288. if (CreateDirectory (multibytepath, NULL)) {
  289. errorcode = 0;
  290. if (log != NULL) log->Add (multibytepath);
  291. } else {
  292. errorcode = GetLastError();
  293. }
  294. // If no error or directory already exists...
  295. if ((errorcode == 0) || (errorcode == ERROR_ALREADY_EXISTS)) {
  296. // Recurse if not at end of string.
  297. if (replacement != L'\0') {
  298. *c = replacement;
  299. valid = Create_Directory (drive, directory, c + 1, remove, log);
  300. } else {
  301. valid = true;
  302. }
  303. // If caller wants it removed (and it didn't already exist) then remove it (ie. just verify that it can be created).
  304. if (remove && (errorcode == 0)) {
  305. if (!RemoveDirectory (multibytepath)) FATAL_SYSTEM_ERROR;
  306. }
  307. } else {
  308. valid = false;
  309. }
  310. } else {
  311. valid = true;
  312. }
  313. return (valid);
  314. }
  315. /***********************************************************************************************
  316. * Cluster_Padding -- *
  317. * *
  318. * INPUT: *
  319. * *
  320. * OUTPUT: *
  321. * *
  322. * WARNINGS: *
  323. * *
  324. * HISTORY: *
  325. * 08/22/01 IML : Created. *
  326. *=============================================================================================*/
  327. __int64 Cluster_Padding (unsigned filecount)
  328. {
  329. // NOTE: Currently, it is not known how to obtain (or if it is possible to obtain) the cluster size
  330. // of a hard disk. According to MS documentation, the largest possible cluster size of FAT16,
  331. // FAT32 and NTFS file systems is 64K (and is more typically 4-16K). Therefore, conservatively
  332. // estimate the cluster size as 64K.
  333. const unsigned clustersize = 0x10000;
  334. __int64 padding = clustersize * filecount;
  335. return (padding);
  336. }
  337. /***********************************************************************************************
  338. * Is_Same_Path -- *
  339. * *
  340. * INPUT: *
  341. * *
  342. * OUTPUT: *
  343. * *
  344. * WARNINGS: *
  345. * *
  346. * HISTORY: *
  347. * 08/22/01 IML : Created. *
  348. *=============================================================================================*/
  349. bool Is_Same_Path (const WideStringClass &path0, const WideStringClass &path1, bool standardize)
  350. {
  351. if (standardize) {
  352. WideStringClass path0copy, path1copy;
  353. Standardize_Path (path0, path0copy);
  354. Standardize_Path (path1, path1copy);
  355. return (path0copy.Compare (path1copy) == 0);
  356. } else {
  357. return (path0.Compare (path1) == 0);
  358. }
  359. }
  360. /***********************************************************************************************
  361. * Is_Sub_Path -- *
  362. * *
  363. * INPUT: *
  364. * *
  365. * OUTPUT: *
  366. * *
  367. * WARNINGS: *
  368. * *
  369. * HISTORY: *
  370. * 08/22/01 IML : Created. *
  371. *=============================================================================================*/
  372. bool Is_Sub_Path (const WideStringClass &path0, const WideStringClass &path1, bool standardize)
  373. {
  374. WideStringClass path0copy, path1copy;
  375. if (standardize) {
  376. Standardize_Path (path0, path0copy);
  377. Standardize_Path (path1, path1copy);
  378. } else {
  379. path0copy = path0;
  380. path1copy = path1;
  381. }
  382. if (wcsstr (path0copy, path1copy) != NULL) {
  383. if (path0copy.Get_Length() == path1copy.Get_Length()) {
  384. return (true);
  385. } else {
  386. WCHAR c;
  387. c = path0copy [path1copy.Get_Length()];
  388. if ((c == L'\\') || (c == L'/')) return (true);
  389. }
  390. }
  391. return (false);
  392. }
  393. /***********************************************************************************************
  394. * Standardize_Path -- *
  395. * *
  396. * INPUT: *
  397. * *
  398. * OUTPUT: *
  399. * *
  400. * WARNINGS: *
  401. * *
  402. * HISTORY: *
  403. * 08/22/01 IML : Created. *
  404. *=============================================================================================*/
  405. WCHAR *Standardize_Path (const WideStringClass &path, WideStringClass &standardpath)
  406. {
  407. WideStringClass t (path);
  408. int i, c;
  409. // Remove leading white space.
  410. i = 0;
  411. while (t [i] == L' ') {
  412. i++;
  413. }
  414. if (i > 0) t.Erase (0, i);
  415. // Remove trailing white space and any trailing slashes.
  416. c = 0;
  417. i = t.Get_Length() - 1;
  418. while ((i >= 0) && ((t [i] == L' ') || (t [i] == L'\\') || (t [i] == L'/'))) {
  419. i--;
  420. c++;
  421. }
  422. if (c > 0) t.Erase (i + 1, c);
  423. // Replace back slashes with forward slashes and change to upper case.
  424. for (i = 0; i < t.Get_Length(); i++) {
  425. if (t [i] == L'/') t [i] = L'\\';
  426. t [i] = towupper (t [i]);
  427. }
  428. standardpath = t;
  429. return (standardpath.Peek_Buffer());
  430. }
  431. /***********************************************************************************************
  432. * Remove_Trailing_Name -- *
  433. * *
  434. * INPUT: *
  435. * *
  436. * OUTPUT: *
  437. * *
  438. * WARNINGS: *
  439. * *
  440. * HISTORY: *
  441. * 08/22/01 IML : Created. *
  442. *=============================================================================================*/
  443. WCHAR *Remove_Trailing_Name (WideStringClass &path)
  444. {
  445. int i, c;
  446. for (i = path.Get_Length() - 1, c = 1; i >= 0; i--, c++) {
  447. if ((path [i] == L'\\') || (path [i] == L'/')) {
  448. path.Erase (i, c);
  449. break;
  450. }
  451. }
  452. return (path.Peek_Buffer());
  453. }
  454. /***********************************************************************************************
  455. * Extract_Suffix_Root -- *
  456. * *
  457. * INPUT: *
  458. * *
  459. * OUTPUT: *
  460. * *
  461. * WARNINGS: *
  462. * *
  463. * HISTORY: *
  464. * 08/22/01 IML : Created. *
  465. *=============================================================================================*/
  466. WCHAR *Extract_Suffix_Root (WideStringClass &path, const WideStringClass &prefixpath)
  467. {
  468. if (wcsstr (path, prefixpath) == path) {
  469. int s, e, c;
  470. s = prefixpath.Get_Length();
  471. if ((path [s] == L'\\') || (path [s] == L'/')) s++;
  472. if (s > 0) path.Erase (0, s);
  473. e = 0;
  474. c = path.Get_Length();
  475. for (e = 0, c = path.Get_Length(); c > 0; e++, c--) {
  476. if ((path [e] == L'\\') || (path [e] == L'/')) {
  477. path.Erase (e, c);
  478. break;
  479. }
  480. }
  481. return (path.Peek_Buffer());
  482. }
  483. return (NULL);
  484. }
  485. /***********************************************************************************************
  486. * Extract_Trailing_Name -- *
  487. * *
  488. * INPUT: *
  489. * *
  490. * OUTPUT: *
  491. * *
  492. * WARNINGS: *
  493. * *
  494. * HISTORY: *
  495. * 08/22/01 IML : Created. *
  496. *=============================================================================================*/
  497. WCHAR *Extract_Trailing_Name (WideStringClass &path)
  498. {
  499. int i;
  500. for (i = path.Get_Length() - 1; i >= 0; i--) {
  501. if ((path [i] == L'\\') || (path [i] == L'/')) {
  502. path.Erase (0, i + 1);
  503. break;
  504. }
  505. }
  506. return (path.Peek_Buffer());
  507. }
  508. /***********************************************************************************************
  509. * Directory_Exists -- *
  510. * *
  511. * INPUT: *
  512. * *
  513. * OUTPUT: *
  514. * *
  515. * WARNINGS: *
  516. * *
  517. * HISTORY: *
  518. * 08/22/01 IML : Created. *
  519. *=============================================================================================*/
  520. bool Directory_Exists (const WideStringClass &path)
  521. {
  522. StringClass multibytepath (path);
  523. DWORD errorcode;
  524. if (CreateDirectory (multibytepath, NULL)) {
  525. errorcode = 0;
  526. } else {
  527. errorcode = GetLastError();
  528. }
  529. if (errorcode == 0) {
  530. if (!RemoveDirectory (multibytepath)) FATAL_SYSTEM_ERROR;
  531. return (false);
  532. } else {
  533. return (errorcode == ERROR_ALREADY_EXISTS);
  534. }
  535. }
  536. /***********************************************************************************************
  537. * Is_System_Directory -- *
  538. * *
  539. * INPUT: *
  540. * *
  541. * OUTPUT: *
  542. * *
  543. * WARNINGS: *
  544. * *
  545. * HISTORY: *
  546. * 08/22/01 IML : Created. *
  547. *=============================================================================================*/
  548. bool Is_System_Directory (const WideStringClass &path)
  549. {
  550. const int DirectoryTypes [] = {
  551. CSIDL_DESKTOP, // 0x0000 <user name>\desktop
  552. CSIDL_PROGRAMS, // 0x0002 <user name>\Start Menu\Programs
  553. CSIDL_PERSONAL, // 0x0005 <user name>\Start Menu\My Documents
  554. CSIDL_FAVORITES, // 0x0006 <user name>Favorites
  555. CSIDL_STARTUP, // 0x0007 <user name>\Start Menu\Programs\Startup
  556. CSIDL_RECENT, // 0x0008 <user name>\Recent
  557. CSIDL_SENDTO, // 0x0009 <user name>\SendTo
  558. CSIDL_STARTMENU, // 0x000b <user name>\Start Menu
  559. CSIDL_DESKTOPDIRECTORY, // 0x0010 <user name>\Desktop
  560. CSIDL_NETHOOD, // 0x0013 <user name>\nethood
  561. CSIDL_FONTS, // 0x0014 windows\fonts
  562. CSIDL_TEMPLATES, // 0x0015 <user name>\Templates
  563. CSIDL_COMMON_STARTMENU, // 0x0016 All Users\Start Menu
  564. CSIDL_COMMON_PROGRAMS, // 0X0017 All Users\Start Menu\Programs
  565. CSIDL_COMMON_STARTUP, // 0x0018 All Users\Start Menu\Programs\Startup
  566. CSIDL_COMMON_DESKTOPDIRECTORY, // 0x0019 All Users\Desktop
  567. CSIDL_APPDATA, // 0x001a <user name>\Application Data
  568. CSIDL_PRINTHOOD, // 0x001b <user name>\PrintHood
  569. CSIDL_COMMON_FAVORITES, // 0x001f All Users\Favorites
  570. CSIDL_INTERNET_CACHE, // 0x0020 <user name>\Local Settings\Temporary Internet Files
  571. CSIDL_COOKIES, // 0x0021 <user name>\Cookies
  572. CSIDL_HISTORY // 0x0022 <user name>\Local Settings\History
  573. };
  574. char multibytesystempath [_MAX_PATH];
  575. WideStringClass systempath;
  576. bool result;
  577. HINSTANCE hinstLib;
  578. // Test for Windows directory.
  579. if (!GetWindowsDirectory (multibytesystempath, _MAX_PATH)) FATAL_SYSTEM_ERROR;
  580. systempath = multibytesystempath;
  581. if (Is_Sub_Path (path, systempath)) return (true);
  582. // Test for System directory.
  583. if (!GetSystemDirectory (multibytesystempath, _MAX_PATH)) FATAL_SYSTEM_ERROR;
  584. systempath = multibytesystempath;
  585. if (Is_Sub_Path (path, systempath)) return (true);
  586. // Get a handle to the DLL module.
  587. result = false;
  588. hinstLib = LoadLibrary ("shfolder.dll");
  589. if (hinstLib != NULL) {
  590. HRESULT (__stdcall * PFNSHGETFOLDERPATHA)(HWND, int, HANDLE, DWORD, LPSTR);
  591. PFNSHGETFOLDERPATHA = ( HRESULT ( __stdcall * )(HWND, int, HANDLE, DWORD, LPSTR)) GetProcAddress( hinstLib, "SHGetFolderPathA" );
  592. if (PFNSHGETFOLDERPATHA != NULL) {
  593. HRESULT hr = 0;
  594. for (int i = 0; i < sizeof (DirectoryTypes) / sizeof(int); i++) {
  595. // Get each of the known directories above and compare to the desired directory.
  596. hr = (*PFNSHGETFOLDERPATHA)( NULL, DirectoryTypes [i], NULL, 0, multibytesystempath);
  597. if (hr == S_OK) {
  598. systempath = multibytesystempath;
  599. if (Is_Sub_Path (path, systempath)) {
  600. result = true;
  601. break;
  602. }
  603. }
  604. }
  605. }
  606. // Free the DLL module.
  607. FreeLibrary (hinstLib);
  608. }
  609. return (result);
  610. }
  611. /***********************************************************************************************
  612. * Get_Current_Directory -- *
  613. * *
  614. * INPUT: *
  615. * *
  616. * OUTPUT: *
  617. * *
  618. * WARNINGS: *
  619. * *
  620. * HISTORY: *
  621. * 08/22/01 IML : Created. *
  622. *=============================================================================================*/
  623. void Get_Current_Directory (WideStringClass &path)
  624. {
  625. StringClass multibytepath;
  626. if (!GetCurrentDirectory (_MAX_PATH, multibytepath.Get_Buffer (MAX_PATH))) FATAL_SYSTEM_ERROR;
  627. path = multibytepath;
  628. }
  629. /***********************************************************************************************
  630. * Generate_Temporary_Pathname -- *
  631. * *
  632. * INPUT: *
  633. * *
  634. * OUTPUT: *
  635. * *
  636. * WARNINGS: *
  637. * *
  638. * HISTORY: *
  639. * 08/22/01 IML : Created. *
  640. *=============================================================================================*/
  641. bool Generate_Temporary_Pathname (const WideStringClass &path, StringClass &multibytetemporarypathname)
  642. {
  643. StringClass multibytepath;
  644. // Create temporary file.
  645. multibytepath = path;
  646. if (!GetTempFileName (multibytepath, "XXX", 0, multibytetemporarypathname.Get_Buffer (_MAX_PATH))) return (false);
  647. return (true);
  648. }
  649. /***********************************************************************************************
  650. * Message_Box -- *
  651. * *
  652. * INPUT: *
  653. * *
  654. * OUTPUT: *
  655. * *
  656. * WARNINGS: *
  657. * *
  658. * HISTORY: *
  659. * 08/22/01 IML : Created. *
  660. *=============================================================================================*/
  661. void Message_Box (const WideStringClass &header, const WideStringClass &errormessage)
  662. {
  663. ShowCursor (true);
  664. MessageBoxExW (NULL, ((WideStringClass) errormessage).Peek_Buffer(), ((WideStringClass) header).Peek_Buffer(), MB_OK | MB_APPLMODAL | MB_SETFOREGROUND, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT));
  665. ShowCursor (false);
  666. }