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.

691 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. utils.c
  5. Abstract:
  6. This source file implements utility functions used by scrnsave.c.
  7. Author:
  8. Jim Schmidt (jimschm) 11-Apr-1997
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #ifdef UNICODE
  13. #error UNICODE cannot be defined
  14. #endif
  15. //
  16. // Declare strings
  17. //
  18. #define DEFMAC(var,str) CHAR var[] = str;
  19. DEFINE_STRINGS
  20. #undef DEFMAC
  21. //
  22. // Temporary buffer
  23. //
  24. static CHAR g_Data[MAX_PATH];
  25. //
  26. // Buffer for string representation of registry keys (for error logging)
  27. //
  28. typedef struct _tagKEYTOSTR {
  29. struct _tagKEYTOSTR *Prev, *Next;
  30. HKEY Key;
  31. CHAR RegKey[];
  32. } KEYTOSTR, *PKEYTOSTR;
  33. static PKEYTOSTR g_Head = NULL;
  34. VOID
  35. pAddKeyToStrMapping (
  36. IN HKEY Key,
  37. IN LPCSTR RootStr,
  38. IN LPCSTR KeyStr
  39. )
  40. {
  41. PKEYTOSTR Node;
  42. DWORD Size;
  43. CHAR FullKeyStr[MAX_PATH];
  44. // We control RootStr and KeyStr, so we know it is less than MAX_PATH in length
  45. wsprintf (FullKeyStr, "%s\\%s", RootStr, KeyStr);
  46. Size = sizeof (KEYTOSTR) + CountStringBytes (FullKeyStr);
  47. Node = (PKEYTOSTR) HeapAlloc (g_hHeap, 0, Size);
  48. if (Node) {
  49. Node->Prev = NULL;
  50. Node->Next = g_Head;
  51. Node->Key = Key;
  52. _mbscpy (Node->RegKey, FullKeyStr);
  53. if (g_Head) {
  54. g_Head->Prev = Node;
  55. }
  56. g_Head = Node;
  57. }
  58. }
  59. PKEYTOSTR
  60. pFindKeyToStrMapping (
  61. IN HKEY Key
  62. )
  63. {
  64. PKEYTOSTR Node;
  65. Node = g_Head;
  66. while (Node) {
  67. if (Node->Key == Key) {
  68. return Node;
  69. }
  70. Node = Node->Next;
  71. }
  72. return NULL;
  73. }
  74. VOID
  75. pRemoveKeyToStrMapping (
  76. IN HKEY Key
  77. )
  78. {
  79. PKEYTOSTR Node;
  80. Node = pFindKeyToStrMapping (Key);
  81. if (!Node) {
  82. return;
  83. }
  84. if (Node->Prev) {
  85. Node->Prev->Next = Node->Next;
  86. } else {
  87. g_Head = Node->Next;
  88. }
  89. if (Node->Next) {
  90. Node->Next->Prev = Node->Prev;
  91. }
  92. HeapFree (g_hHeap, 0, Node);
  93. }
  94. VOID
  95. LogRegistryError (
  96. IN HKEY Key,
  97. IN LPCSTR ValueName
  98. )
  99. {
  100. DWORD rc = GetLastError();
  101. LPCSTR FullKeyStr;
  102. PKEYTOSTR Node;
  103. Node = pFindKeyToStrMapping (Key);
  104. if (Node) {
  105. FullKeyStr = Node->RegKey;
  106. } else {
  107. FullKeyStr = S_DEFAULT_KEYSTR;
  108. }
  109. LOG ((LOG_ERROR, MSG_REGISTRY_ERROR, g_User, rc, FullKeyStr, ValueName));
  110. }
  111. VOID
  112. GenerateFilePaths (
  113. VOID
  114. )
  115. {
  116. INT Len;
  117. // Safety (unexpected condition)
  118. if (!g_WorkingDirectory) {
  119. return;
  120. }
  121. Len = CountStringBytes (g_WorkingDirectory) + sizeof(S_SETTINGS_MASK);
  122. g_SettingsFile = (LPSTR) HeapAlloc (g_hHeap, 0, Len);
  123. if (!g_SettingsFile) {
  124. return;
  125. }
  126. wsprintf (g_SettingsFile, S_SETTINGS_MASK, g_WorkingDirectory);
  127. Len = CountStringBytes (g_WorkingDirectory) + sizeof(S_MIGINF_MASK);
  128. g_MigrateDotInf = (LPSTR) HeapAlloc (g_hHeap, 0, Len);
  129. if (!g_MigrateDotInf) {
  130. return;
  131. }
  132. wsprintf (g_MigrateDotInf, S_MIGINF_MASK, g_WorkingDirectory);
  133. }
  134. HKEY
  135. OpenRegKey (
  136. IN HKEY RootKey,
  137. IN LPCSTR KeyStr
  138. )
  139. {
  140. HKEY Key;
  141. LONG rc;
  142. rc = RegOpenKeyEx (RootKey, KeyStr, 0, KEY_ALL_ACCESS, &Key);
  143. if (rc != ERROR_SUCCESS) {
  144. SetLastError (rc);
  145. return NULL;
  146. }
  147. pAddKeyToStrMapping (Key, S_HKR, KeyStr);
  148. return Key;
  149. }
  150. HKEY
  151. CreateRegKey (
  152. IN HKEY RootKey,
  153. IN LPCSTR KeyStr
  154. )
  155. {
  156. HKEY Key;
  157. LONG rc;
  158. DWORD DontCare;
  159. pAddKeyToStrMapping (NULL, S_HKR, KeyStr);
  160. rc = RegCreateKeyEx (RootKey, KeyStr, 0, S_EMPTY, 0,
  161. KEY_ALL_ACCESS, NULL, &Key, &DontCare);
  162. if (rc != ERROR_SUCCESS) {
  163. SetLastError (rc);
  164. LogRegistryError (NULL, S_EMPTY);
  165. pRemoveKeyToStrMapping (NULL);
  166. return NULL;
  167. }
  168. pRemoveKeyToStrMapping (NULL);
  169. pAddKeyToStrMapping (Key, S_HKR, KeyStr);
  170. return Key;
  171. }
  172. VOID
  173. CloseRegKey (
  174. IN HKEY Key
  175. )
  176. {
  177. pRemoveKeyToStrMapping (Key);
  178. RegCloseKey (Key);
  179. }
  180. LPCSTR
  181. GetRegValueString (
  182. IN HKEY Key,
  183. IN LPCSTR ValueName
  184. )
  185. {
  186. static CHAR DataBuf[MAX_PATH];
  187. DWORD Size;
  188. LONG rc;
  189. DWORD Type;
  190. DWORD d;
  191. Size = MAX_PATH;
  192. rc = RegQueryValueEx (Key, ValueName, NULL, &Type, DataBuf, &Size);
  193. SetLastError (rc);
  194. if (rc != ERROR_SUCCESS) {
  195. return NULL;
  196. }
  197. if (Type == REG_DWORD) {
  198. d = *((PDWORD) DataBuf);
  199. wsprintf (DataBuf, "%u", d);
  200. }
  201. else if (Type != REG_SZ) {
  202. return NULL;
  203. }
  204. return DataBuf;
  205. }
  206. BOOL
  207. SetRegValueString (
  208. HKEY Key,
  209. LPCSTR ValueName,
  210. LPCSTR ValueStr
  211. )
  212. {
  213. LONG rc;
  214. LPCSTR p;
  215. p = _mbschr (ValueStr, 0);
  216. p++;
  217. rc = RegSetValueEx (Key, ValueName, 0, REG_SZ, ValueStr, p - ValueStr);
  218. SetLastError (rc);
  219. if (rc != ERROR_SUCCESS) {
  220. LogRegistryError (Key, ValueName);
  221. }
  222. return rc == ERROR_SUCCESS;
  223. }
  224. LPCSTR
  225. GetScrnSaveExe (
  226. VOID
  227. )
  228. {
  229. CHAR IniFileSetting[MAX_PATH];
  230. GetPrivateProfileString (
  231. S_BOOT,
  232. S_SCRNSAVE_EXE,
  233. S_EMPTY,
  234. IniFileSetting,
  235. MAX_PATH,
  236. S_SYSTEM_INI
  237. );
  238. if (!IniFileSetting[0]) {
  239. return NULL;
  240. }
  241. if (!OurGetLongPathName (IniFileSetting, g_Data)) {
  242. // File does not exist
  243. return NULL;
  244. }
  245. return g_Data[0] ? g_Data : NULL;
  246. }
  247. INT
  248. _mbsbytes (
  249. IN LPCSTR str
  250. )
  251. {
  252. LPCSTR p;
  253. // Find the nul terminator and return the number of bytes
  254. // occupied by the characters in the string, but don't
  255. // include the nul.
  256. p = _mbschr (str, 0);
  257. return (p - str);
  258. }
  259. DWORD
  260. CountStringBytes (
  261. IN LPCSTR str
  262. )
  263. {
  264. // Return bytes in string, plus 1 for the nul
  265. return _mbsbytes (str) + 1;
  266. }
  267. DWORD
  268. CountMultiStringBytes (
  269. IN LPCSTR str
  270. )
  271. {
  272. LPCSTR p;
  273. INT Total = 0;
  274. INT Bytes;
  275. p = str;
  276. do {
  277. Bytes = CountStringBytes (p);
  278. p += Bytes;
  279. Total += Bytes;
  280. } while (Bytes > 1);
  281. return Total;
  282. }
  283. LPSTR
  284. CopyStringAtoB (
  285. OUT LPSTR mbstrDest,
  286. IN LPCSTR mbstrStart,
  287. IN LPCSTR mbstrEnd // first char NOT to copy
  288. )
  289. {
  290. LPSTR mbstrOrg;
  291. mbstrOrg = mbstrDest;
  292. // Assume mbstrEnd is on a lead byte
  293. while (mbstrStart < mbstrEnd) {
  294. if (isleadbyte (*mbstrStart)) {
  295. *mbstrDest = *mbstrStart;
  296. mbstrDest++;
  297. mbstrStart++;
  298. }
  299. *mbstrDest = *mbstrStart;
  300. mbstrDest++;
  301. mbstrStart++;
  302. }
  303. *mbstrDest = 0;
  304. return mbstrOrg;
  305. }
  306. LPSTR
  307. AppendStr (
  308. OUT LPSTR mbstrDest,
  309. IN LPCSTR mbstrSrc
  310. )
  311. {
  312. // Advance mbstrDest to end of string
  313. mbstrDest = _mbschr (mbstrDest, 0);
  314. // Copy string
  315. while (*mbstrSrc) {
  316. *mbstrDest = *mbstrSrc++;
  317. if (isleadbyte (*mbstrDest)) {
  318. mbstrDest++;
  319. *mbstrDest = *mbstrSrc++;
  320. }
  321. mbstrDest++;
  322. }
  323. *mbstrDest = 0;
  324. return mbstrDest;
  325. }
  326. BOOL
  327. pFindShortName (
  328. IN LPCTSTR WhatToFind,
  329. OUT LPTSTR Buffer
  330. )
  331. {
  332. WIN32_FIND_DATA fd;
  333. HANDLE hFind;
  334. hFind = FindFirstFile (WhatToFind, &fd);
  335. if (hFind == INVALID_HANDLE_VALUE) {
  336. return FALSE;
  337. }
  338. FindClose (hFind);
  339. _mbscpy (Buffer, fd.cFileName);
  340. return TRUE;
  341. }
  342. BOOL
  343. OurGetLongPathName (
  344. IN LPCSTR ShortPath,
  345. OUT LPSTR Buffer
  346. )
  347. {
  348. CHAR FullPath[MAX_PATH];
  349. LPSTR FilePart;
  350. LPSTR BufferEnd;
  351. LPSTR p, p2;
  352. CHAR c;
  353. //
  354. // Convert ShortPath into complete path name
  355. //
  356. if (!_mbschr (ShortPath, TEXT('\\'))) {
  357. if (!SearchPath (NULL, ShortPath, NULL, MAX_PATH, FullPath, &FilePart)) {
  358. return FALSE;
  359. }
  360. } else {
  361. GetFullPathName (ShortPath, MAX_PATH, FullPath, &FilePart);
  362. }
  363. //
  364. // Convert short path to long path
  365. //
  366. p = FullPath;
  367. // Don't process non-local paths
  368. if (!(*p) || _mbsnextc (_mbsinc (p)) != TEXT(':')) {
  369. _mbscpy (Buffer, FullPath);
  370. return TRUE;
  371. }
  372. p = _mbsinc (p);
  373. p = _mbsinc (p);
  374. if (_mbsnextc (p) != TEXT('\\')) {
  375. _mbscpy (Buffer, FullPath);
  376. return TRUE;
  377. }
  378. // Copy drive letter to buffer
  379. p = _mbsinc (p);
  380. CopyStringAtoB (Buffer, FullPath, p);
  381. BufferEnd = _mbschr (Buffer, 0);
  382. // Convert each portion of the path
  383. do {
  384. // Locate end of this file or dir
  385. p2 = _mbschr (p, TEXT('\\'));
  386. if (!p2) {
  387. p = _mbschr (p, 0);
  388. } else {
  389. p = p2;
  390. }
  391. // Look up file
  392. c = *p;
  393. *p = 0;
  394. if (!pFindShortName (FullPath, BufferEnd)) {
  395. return FALSE;
  396. }
  397. *p = c;
  398. // Move on to next part of path
  399. BufferEnd = _mbschr (BufferEnd, 0);
  400. if (*p) {
  401. p = _mbsinc (p);
  402. BufferEnd = AppendStr (BufferEnd, TEXT("\\"));
  403. }
  404. } while (*p);
  405. return TRUE;
  406. }
  407. BOOL
  408. CreateScreenSaverParamKey (
  409. IN LPCSTR ScreenSaverName,
  410. IN LPCSTR ValueName,
  411. OUT LPSTR Buffer
  412. )
  413. {
  414. //
  415. // Make sure we cannot create a string bigger than MAX_PATH
  416. //
  417. if (_mbslen (ScreenSaverName) + 4 + _mbslen (ValueName) > MAX_PATH) {
  418. return FALSE;
  419. }
  420. //
  421. // Format the string with length of screen saver name, screen saver name,
  422. // and value name.
  423. //
  424. wsprintf (Buffer, "%03u/%s/%s", _mbslen (ScreenSaverName), ScreenSaverName, ValueName);
  425. return TRUE;
  426. }
  427. BOOL
  428. DecodeScreenSaverParamKey (
  429. IN LPCSTR EncodedString,
  430. OUT LPSTR ScreenSaverName,
  431. OUT LPSTR ValueName
  432. )
  433. {
  434. INT Len;
  435. //
  436. // Validate encoded string. It is in the form of ###/screen saver name/value name.
  437. //
  438. Len = atoi (EncodedString);
  439. if (Len < 0 || Len >= MAX_PATH || (Len - 5) > (INT) _mbslen (EncodedString)) {
  440. return FALSE;
  441. }
  442. if (EncodedString[3] != '/' || EncodedString[4 + Len] != '/') {
  443. return FALSE;
  444. }
  445. if (_mbslen (EncodedString + 5 + Len) >= MAX_PATH) {
  446. return FALSE;
  447. }
  448. //
  449. // Extract screen saver name and value name
  450. //
  451. _mbsncpy (ScreenSaverName, EncodedString + 4, Len);
  452. ScreenSaverName[Len] = 0;
  453. _mbscpy (ValueName, EncodedString + 5 + Len);
  454. return TRUE;
  455. }
  456. LPSTR
  457. _mbsistr (
  458. IN LPCSTR mbstrStr,
  459. IN LPCSTR mbstrSubStr
  460. )
  461. {
  462. LPCSTR mbstrStart, mbstrStrPos, mbstrSubStrPos;
  463. LPCSTR mbstrEnd;
  464. mbstrEnd = (LPSTR) ((LPBYTE) mbstrStr + _mbsbytes (mbstrStr) - _mbsbytes (mbstrSubStr));
  465. for (mbstrStart = mbstrStr ; mbstrStart <= mbstrEnd ; mbstrStart = _mbsinc (mbstrStart)) {
  466. mbstrStrPos = mbstrStart;
  467. mbstrSubStrPos = mbstrSubStr;
  468. while (*mbstrSubStrPos &&
  469. _mbctolower ((INT) _mbsnextc (mbstrSubStrPos)) == _mbctolower ((INT) _mbsnextc (mbstrStrPos)))
  470. {
  471. mbstrStrPos = _mbsinc (mbstrStrPos);
  472. mbstrSubStrPos = _mbsinc (mbstrSubStrPos);
  473. }
  474. if (!(*mbstrSubStrPos))
  475. return (LPSTR) mbstrStart;
  476. }
  477. return NULL;
  478. }
  479. VOID
  480. DeletePartOfString (
  481. IN LPSTR Buffer,
  482. IN DWORD CharsToDelete
  483. )
  484. {
  485. LPSTR p;
  486. DWORD d;
  487. p = Buffer;
  488. for (d = 0 ; *p && d < CharsToDelete ; d++) {
  489. p = _mbsinc (p);
  490. }
  491. if (!(*p)) {
  492. *Buffer = 0;
  493. } else {
  494. MoveMemory (Buffer, p, CountStringBytes(p));
  495. }
  496. }
  497. VOID
  498. InsertStringInString (
  499. IN LPSTR Buffer,
  500. IN LPCSTR StringToInsert
  501. )
  502. {
  503. DWORD BytesToMove;
  504. DWORD BytesOfInsertedString;
  505. BytesToMove = CountStringBytes (Buffer);
  506. BytesOfInsertedString = _mbsbytes(StringToInsert);
  507. MoveMemory (Buffer + BytesOfInsertedString,
  508. Buffer,
  509. BytesToMove
  510. );
  511. _mbsncpy (Buffer, StringToInsert, _mbslen (StringToInsert));
  512. }
  513. PCSTR
  514. ParseMessage (
  515. UINT MessageId,
  516. ...
  517. )
  518. {
  519. va_list list;
  520. PSTR RetStr = NULL;
  521. UINT RetStrSize;
  522. va_start (list, MessageId);
  523. RetStrSize = FormatMessageA (
  524. FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE,
  525. (PSTR) g_hInst,
  526. MessageId,
  527. 0,
  528. (PSTR) (&RetStr),
  529. 1,
  530. &list
  531. );
  532. if (!RetStrSize && RetStr) {
  533. *RetStr = 0;
  534. }
  535. va_end (list);
  536. return RetStr;
  537. }
  538. VOID
  539. FreeMessage (
  540. PCSTR Message
  541. )
  542. {
  543. if (Message) {
  544. LocalFree ((PSTR) Message);
  545. }
  546. }