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.

771 lines
15 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. common9x.c
  5. Abstract:
  6. Common functionality between various parts of Win9x-side processing.
  7. The routines in this library are shared only by other LIBs in the
  8. w95upg tree.
  9. Author:
  10. Jim Schmidt (jimschm) 18-Aug-1998
  11. Revision History:
  12. Name (alias) Date Description
  13. --*/
  14. #include "pch.h"
  15. static PMAPSTRUCT g_EnvVars9x;
  16. typedef struct {
  17. UINT MapSize;
  18. UINT Icons;
  19. BYTE Map[];
  20. } ICONMAP, *PICONMAP;
  21. static HASHTABLE g_IconMaps;
  22. static POOLHANDLE g_IconMapPool;
  23. static BYTE g_Bits[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
  24. BOOL
  25. WINAPI
  26. Common9x_Entry (
  27. IN HINSTANCE Instance,
  28. IN DWORD Reason,
  29. IN PVOID lpv
  30. )
  31. /*++
  32. Routine Description:
  33. Common9x_Entry is a DllMain-like init funciton, called by w95upg\dll.
  34. This function is called at process attach and detach.
  35. Arguments:
  36. Instance - (OS-supplied) instance handle for the DLL
  37. Reason - (OS-supplied) indicates attach or detatch from process or
  38. thread
  39. lpv - unused
  40. Return Value:
  41. Return value is always TRUE (indicating successful init).
  42. --*/
  43. {
  44. switch (Reason) {
  45. case DLL_PROCESS_ATTACH:
  46. //
  47. // used by userenum.c
  48. //
  49. if(!pSetupInitializeUtils()) {
  50. return FALSE;
  51. }
  52. break;
  53. case DLL_PROCESS_DETACH:
  54. pSetupUninitializeUtils();
  55. break;
  56. }
  57. return TRUE;
  58. }
  59. BOOL
  60. EnumFirstJoystick (
  61. OUT PJOYSTICK_ENUM EnumPtr
  62. )
  63. {
  64. ZeroMemory (EnumPtr, sizeof (JOYSTICK_ENUM));
  65. EnumPtr->Root = OpenRegKeyStr (TEXT("HKLM\\System\\CurrentControlSet\\Control\\MediaResources\\joystick\\<FixedKey>\\CurrentJoystickSettings"));
  66. if (!EnumPtr->Root) {
  67. return FALSE;
  68. }
  69. return EnumNextJoystick (EnumPtr);
  70. }
  71. BOOL
  72. EnumNextJoystick (
  73. IN OUT PJOYSTICK_ENUM EnumPtr
  74. )
  75. {
  76. TCHAR ValueName[MAX_REGISTRY_VALUE_NAME];
  77. PCTSTR Data;
  78. //
  79. // Ping the root key for Joystick<n>OEMName and Joystick<n>OEMCallout
  80. //
  81. EnumPtr->JoyId++;
  82. wsprintf (ValueName, TEXT("Joystick%uOEMName"), EnumPtr->JoyId);
  83. Data = GetRegValueString (EnumPtr->Root, ValueName);
  84. if (!Data) {
  85. AbortJoystickEnum (EnumPtr);
  86. return FALSE;
  87. }
  88. StringCopy (EnumPtr->JoystickName, Data);
  89. MemFree (g_hHeap, 0, Data);
  90. wsprintf (ValueName, TEXT("Joystick%uOEMCallout"), EnumPtr->JoyId);
  91. Data = GetRegValueString (EnumPtr->Root, ValueName);
  92. if (!Data) {
  93. AbortJoystickEnum (EnumPtr);
  94. return FALSE;
  95. }
  96. StringCopy (EnumPtr->JoystickDriver, Data);
  97. MemFree (g_hHeap, 0, Data);
  98. return TRUE;
  99. }
  100. VOID
  101. AbortJoystickEnum (
  102. IN PJOYSTICK_ENUM EnumPtr
  103. )
  104. {
  105. if (EnumPtr->Root) {
  106. CloseRegKey (EnumPtr->Root);
  107. }
  108. ZeroMemory (EnumPtr, sizeof (JOYSTICK_ENUM));
  109. }
  110. typedef struct {
  111. PCTSTR Text;
  112. PCTSTR Button1;
  113. PCTSTR Button2;
  114. } TWOBUTTONBOXPARAMS, *PTWOBUTTONBOXPARAMS;
  115. BOOL
  116. CALLBACK
  117. TwoButtonProc (
  118. HWND hdlg,
  119. UINT uMsg,
  120. WPARAM wParam,
  121. LPARAM lParam
  122. )
  123. {
  124. PTWOBUTTONBOXPARAMS params;
  125. switch (uMsg) {
  126. case WM_INITDIALOG:
  127. params = (PTWOBUTTONBOXPARAMS) lParam;
  128. SetWindowText (GetDlgItem (hdlg, IDC_TWOBUTTON_TEXT), params->Text);
  129. SetWindowText (GetDlgItem (hdlg, IDBUTTON1), params->Button1);
  130. SetWindowText (GetDlgItem (hdlg, IDBUTTON2), params->Button2);
  131. CenterWindow (hdlg, GetDesktopWindow());
  132. return FALSE;
  133. case WM_COMMAND:
  134. EndDialog (hdlg, LOWORD (wParam));
  135. break;
  136. }
  137. return FALSE;
  138. }
  139. LRESULT
  140. TwoButtonBox (
  141. IN HWND Window,
  142. IN PCTSTR Text,
  143. IN PCTSTR Button1,
  144. IN PCTSTR Button2
  145. )
  146. {
  147. TWOBUTTONBOXPARAMS params;
  148. params.Text = Text;
  149. params.Button1 = Button1;
  150. params.Button2 = Button2;
  151. return DialogBoxParam (
  152. g_hInst,
  153. MAKEINTRESOURCE(IDD_TWOBUTTON_DLG),
  154. Window,
  155. TwoButtonProc,
  156. (LPARAM) &params
  157. );
  158. }
  159. BOOL
  160. DontTouchThisFile (
  161. IN PCTSTR FileName
  162. )
  163. {
  164. TCHAR key[MEMDB_MAX];
  165. RemoveOperationsFromPath (FileName, ALL_CHANGE_OPERATIONS);
  166. MemDbBuildKey (key, MEMDB_CATEGORY_DEFERREDANNOUNCE, FileName, NULL, NULL);
  167. MemDbDeleteTree (key);
  168. return TRUE;
  169. }
  170. VOID
  171. ReplaceOneEnvVar (
  172. IN OUT PCTSTR *NewString,
  173. IN PCTSTR Base,
  174. IN PCTSTR Variable,
  175. IN PCTSTR Value
  176. )
  177. {
  178. PCTSTR FreeMe;
  179. //
  180. // The Base string cannot be freed, but a previous NewString
  181. // value must be freed.
  182. //
  183. FreeMe = *NewString; // FreeMe will be NULL if no replacement string
  184. // has been generated yet
  185. if (FreeMe) {
  186. Base = FreeMe; // Previously generated replacement string is now the source
  187. }
  188. *NewString = StringSearchAndReplace (Base, Variable, Value);
  189. if (*NewString == NULL) {
  190. // Keep previously generated replacement string
  191. *NewString = FreeMe;
  192. } else if (FreeMe) {
  193. // Free previously generated replacmenet string
  194. FreePathString (FreeMe);
  195. }
  196. //
  197. // *NewString is either:
  198. //
  199. // 1. It's original value (which may be NULL)
  200. // 2. A new string that will need to be freed with FreePathString
  201. //
  202. }
  203. VOID
  204. Init9xEnvironmentVariables (
  205. VOID
  206. )
  207. {
  208. DestroyStringMapping (g_EnvVars9x);
  209. g_EnvVars9x = CreateStringMapping();
  210. AddStringMappingPair (g_EnvVars9x, S_WINDIR_ENV, g_WinDir);
  211. AddStringMappingPair (g_EnvVars9x, S_SYSTEMDIR_ENV, g_SystemDir);
  212. AddStringMappingPair (g_EnvVars9x, S_SYSTEM32DIR_ENV, g_System32Dir);
  213. AddStringMappingPair (g_EnvVars9x, S_SYSTEMDRIVE_ENV, g_WinDrive);
  214. AddStringMappingPair (g_EnvVars9x, S_BOOTDRIVE_ENV, g_BootDrivePath);
  215. AddStringMappingPair (g_EnvVars9x, S_PROGRAMFILES_ENV, g_ProgramFilesDir);
  216. AddStringMappingPair (g_EnvVars9x, S_COMMONPROGRAMFILES_ENV, g_ProgramFilesCommonDir);
  217. }
  218. BOOL
  219. Expand9xEnvironmentVariables (
  220. IN PCSTR SourceString,
  221. OUT PSTR DestinationString, // can be the same as SourceString
  222. IN INT DestSizeInBytes
  223. )
  224. {
  225. BOOL Changed;
  226. Changed = MappingSearchAndReplaceEx (
  227. g_EnvVars9x,
  228. SourceString,
  229. DestinationString,
  230. 0,
  231. NULL,
  232. DestSizeInBytes,
  233. STRMAP_ANY_MATCH,
  234. NULL,
  235. NULL
  236. );
  237. return Changed;
  238. }
  239. VOID
  240. CleanUp9xEnvironmentVariables (
  241. VOID
  242. )
  243. {
  244. DestroyStringMapping (g_EnvVars9x);
  245. }
  246. BOOL
  247. pIsGuid (
  248. PCTSTR Key
  249. )
  250. /*++
  251. Routine Description:
  252. pIsGuid examines the string specified by Key and determines if it
  253. is the correct length and has dashes at the correct locations.
  254. Arguments:
  255. Key - The string that may or may not be a GUID
  256. Return Value:
  257. TRUE if Key is a GUID (and only a GUID), or FALSE if not.
  258. --*/
  259. {
  260. PCTSTR p;
  261. int i;
  262. DWORD DashesFound = 0;
  263. if (CharCount (Key) != 38) {
  264. return FALSE;
  265. }
  266. for (i = 0, p = Key ; *p ; p = _tcsinc (p), i++) {
  267. if (_tcsnextc (p) == TEXT('-')) {
  268. if (i != 9 && i != 14 && i != 19 && i != 24) {
  269. DEBUGMSG ((DBG_NAUSEA, "%s is not a GUID", Key));
  270. return FALSE;
  271. }
  272. } else if (i == 9 || i == 14 || i == 19 || i == 24) {
  273. DEBUGMSG ((DBG_NAUSEA, "%s is not a GUID", Key));
  274. return FALSE;
  275. }
  276. }
  277. return TRUE;
  278. }
  279. BOOL
  280. FixGuid (
  281. IN PCTSTR Guid,
  282. OUT PTSTR NewGuid // can be the same as Guid
  283. )
  284. {
  285. TCHAR NewData[MAX_GUID];
  286. if (pIsGuid (Guid)) {
  287. if (NewGuid != Guid) {
  288. StringCopy (NewGuid, Guid);
  289. }
  290. return TRUE;
  291. }
  292. //
  293. // Try fixing GUID -- sometimes the braces are missing
  294. //
  295. wsprintf (NewData, TEXT("{%s}"), Guid);
  296. if (pIsGuid (NewData)) {
  297. StringCopy (NewGuid, NewData);
  298. return TRUE;
  299. }
  300. return FALSE;
  301. }
  302. BOOL
  303. IsGuid (
  304. IN PCTSTR Guid,
  305. IN BOOL MustHaveBraces
  306. )
  307. {
  308. TCHAR NewData[MAX_GUID];
  309. if (pIsGuid (Guid)) {
  310. return TRUE;
  311. }
  312. if (MustHaveBraces) {
  313. return FALSE;
  314. }
  315. //
  316. // Try fixing GUID -- sometimes the braces are missing
  317. //
  318. wsprintf (NewData, TEXT("{%s}"), Guid);
  319. if (pIsGuid (NewData)) {
  320. return TRUE;
  321. }
  322. return FALSE;
  323. }
  324. VOID
  325. pParseMapRanges (
  326. IN PCTSTR List,
  327. OUT PGROWBUFFER Ranges, OPTIONAL
  328. OUT PINT HighestNumber OPTIONAL
  329. )
  330. {
  331. MULTISZ_ENUM e;
  332. PTSTR ParsePos;
  333. INT From;
  334. INT To;
  335. INT Max = 0;
  336. PINT Ptr;
  337. if (EnumFirstMultiSz (&e, List)) {
  338. do {
  339. //
  340. // The INF has either a single resource ID, or
  341. // a range, separated by a dash.
  342. //
  343. if (_tcschr (e.CurrentString, TEXT('-'))) {
  344. From = (INT) _tcstoul (e.CurrentString, &ParsePos, 10);
  345. ParsePos = (PTSTR) SkipSpace (ParsePos);
  346. if (_tcsnextc (ParsePos) != TEXT('-')) {
  347. DEBUGMSG ((DBG_WHOOPS, "Ignoring invalid resource ID %s", e.CurrentString));
  348. continue;
  349. }
  350. ParsePos = (PTSTR) SkipSpace (_tcsinc (ParsePos));
  351. To = (INT) _tcstoul (ParsePos, &ParsePos, 10);
  352. if (*ParsePos) {
  353. DEBUGMSG ((DBG_WHOOPS, "Ignoring garbage resource ID %s", e.CurrentString));
  354. continue;
  355. }
  356. if (From > To) {
  357. DEBUGMSG ((DBG_WHOOPS, "Ignoring invalid resource ID range %s", e.CurrentString));
  358. continue;
  359. }
  360. Max = max (Max, To);
  361. } else {
  362. From = To = (INT) _tcstoul (e.CurrentString, &ParsePos, 10);
  363. if (*ParsePos) {
  364. DEBUGMSG ((DBG_WHOOPS, "Ignoring garbage resource %s", e.CurrentString));
  365. continue;
  366. }
  367. Max = max (Max, From);
  368. }
  369. if (Ranges) {
  370. Ptr = (PINT) GrowBuffer (Ranges, sizeof (INT));
  371. *Ptr = From;
  372. Ptr = (PINT) GrowBuffer (Ranges, sizeof (INT));
  373. *Ptr = To;
  374. }
  375. } while (EnumNextMultiSz (&e));
  376. }
  377. if (HighestNumber) {
  378. *HighestNumber = Max;
  379. }
  380. }
  381. VOID
  382. InitializeKnownGoodIconMap (
  383. VOID
  384. )
  385. {
  386. PICONMAP Map;
  387. INT Highest;
  388. INT From;
  389. INT To;
  390. INFSTRUCT is = INITINFSTRUCT_GROWBUFFER;
  391. PCTSTR Module;
  392. PCTSTR List;
  393. PCTSTR IconsInModule;
  394. GROWBUFFER Ranges = GROWBUF_INIT;
  395. PINT Ptr;
  396. PINT End;
  397. UINT MapDataSize;
  398. PBYTE Byte;
  399. BYTE Bit;
  400. if (g_IconMaps) {
  401. return;
  402. }
  403. if (g_Win95UpgInf == INVALID_HANDLE_VALUE) {
  404. MYASSERT (g_ToolMode);
  405. return;
  406. }
  407. g_IconMaps = HtAllocWithData (sizeof (PICONMAP));
  408. g_IconMapPool = PoolMemInitNamedPool ("IconMap");
  409. //
  410. // Enumerate the lines in win95upg.inf and build a map table for each
  411. //
  412. if (InfFindFirstLine (g_Win95UpgInf, S_KNOWN_GOOD_ICON_MODULES, NULL, &is)) {
  413. do {
  414. //
  415. // Parse the INF format into a binary struct
  416. //
  417. List = InfGetMultiSzField (&is, 2);
  418. pParseMapRanges (List, &Ranges, &Highest);
  419. if (!Ranges.End) {
  420. continue;
  421. }
  422. //
  423. // Allocate a map struct
  424. //
  425. MapDataSize = (Highest / 8) + 1;
  426. Map = PoolMemGetMemory (g_IconMapPool, sizeof (ICONMAP) + MapDataSize);
  427. //
  428. // Fill in the map
  429. //
  430. Map->MapSize = Highest;
  431. ZeroMemory (Map->Map, MapDataSize);
  432. Ptr = (PINT) Ranges.Buf;
  433. End = (PINT) (Ranges.Buf + Ranges.End);
  434. while (Ptr < End) {
  435. From = *Ptr++;
  436. To = *Ptr++;
  437. while (From <= To) {
  438. Byte = Map->Map + (From / 8);
  439. Bit = g_Bits[From & 7];
  440. *Byte |= Bit;
  441. From++;
  442. }
  443. }
  444. FreeGrowBuffer (&Ranges);
  445. IconsInModule = InfGetStringField (&is, 1);
  446. if (IconsInModule) {
  447. Map->Icons = _tcstoul (IconsInModule, NULL, 10);
  448. }
  449. else {
  450. continue;
  451. }
  452. //
  453. // Cross-reference the map with the module name via a hash table
  454. //
  455. Module = InfGetStringField (&is, 0);
  456. if (!Module || !*Module) {
  457. continue;
  458. }
  459. HtAddStringAndData (g_IconMaps, Module, &Map);
  460. } while (InfFindNextLine (&is));
  461. }
  462. InfCleanUpInfStruct (&is);
  463. }
  464. VOID
  465. CleanUpKnownGoodIconMap (
  466. VOID
  467. )
  468. {
  469. if (g_IconMaps) {
  470. HtFree (g_IconMaps);
  471. g_IconMaps = NULL;
  472. }
  473. if (g_IconMapPool) {
  474. PoolMemDestroyPool (g_IconMapPool);
  475. g_IconMapPool = NULL;
  476. }
  477. }
  478. BOOL
  479. IsIconKnownGood (
  480. IN PCTSTR FileSpec,
  481. IN INT Index
  482. )
  483. {
  484. PCTSTR Module;
  485. PICONMAP Map;
  486. PBYTE Byte;
  487. BYTE Bit;
  488. TCHAR node[MEMDB_MAX];
  489. Module = GetFileNameFromPath (FileSpec);
  490. MYASSERT (Module);
  491. //
  492. // Check icon against moved icons
  493. //
  494. wsprintf (node, MEMDB_CATEGORY_ICONS_MOVED TEXT("\\%s\\%i"), FileSpec, Index);
  495. if (MemDbGetValue (node, NULL)) {
  496. return TRUE;
  497. }
  498. //
  499. // If a path is specified, make sure it is in either %windir% or %windir%\system.
  500. //
  501. if (Module > (FileSpec + 2)) {
  502. if (!StringIMatchCharCount (FileSpec, g_WinDirWack, g_WinDirWackChars) &&
  503. !StringIMatchCharCount (FileSpec, g_SystemDirWack, g_SystemDirWackChars)
  504. ) {
  505. return FALSE;
  506. }
  507. }
  508. //
  509. // Test if there is an icon map for this module, then check the map
  510. //
  511. if (!HtFindStringAndData (g_IconMaps, Module, &Map)) {
  512. return FALSE;
  513. }
  514. //
  515. // If the icon index is a positive number, then it is a sequential
  516. // ID. If it is a negative number, then it is a resource ID.
  517. //
  518. if (Index >= 0) {
  519. return (UINT) Index <= Map->Icons;
  520. }
  521. Index = -Index;
  522. if ((UINT) Index > Map->MapSize) {
  523. return FALSE;
  524. }
  525. Byte = Map->Map + (Index / 8);
  526. Bit = g_Bits[Index & 7];
  527. return *Byte & Bit;
  528. }
  529. BOOL
  530. TreatAsGood (
  531. IN PCTSTR FullPath
  532. )
  533. /*++
  534. Routine Description:
  535. TreatAsGood checks the registry to see if a file is listed as good. If
  536. this is the case, then setup processing is skipped. This is currently
  537. used for TWAIN data sources, run keys and CPLs.
  538. Arguments:
  539. FullPath - Specifies the full path of the file.
  540. Return Value:
  541. TRUE if the file should be treated as known good, FALSE otherwise.
  542. --*/
  543. {
  544. HKEY Key;
  545. REGVALUE_ENUM e;
  546. BOOL b = FALSE;
  547. PCTSTR str;
  548. Key = OpenRegKeyStr (TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup\\KnownGood"));
  549. if (Key) {
  550. if (EnumFirstRegValue (&e, Key)) {
  551. do {
  552. str = GetRegValueString (Key, e.ValueName);
  553. if (str) {
  554. b = StringIMatch (FullPath, str);
  555. MemFree (g_hHeap, 0, str);
  556. DEBUGMSG_IF ((b, DBG_VERBOSE, "File %s is known-good", FullPath));
  557. }
  558. } while (!b && EnumNextRegValue (&e));
  559. }
  560. CloseRegKey (Key);
  561. }
  562. return b;
  563. }