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.

976 lines
25 KiB

  1. /*
  2. * Microsoft Confidential
  3. * Copyright (C) Microsoft Corporation 1991
  4. * All Rights Reserved.
  5. *
  6. *
  7. * PIFSUB.C
  8. * Misc. subroutines for PIFMGR.DLL
  9. *
  10. * History:
  11. * Created 31-Jul-1992 3:30pm by Jeff Parsons
  12. */
  13. #include "shellprv.h"
  14. #pragma hdrstop
  15. // shell priv can alter the definition of IsDBCSLeadByte!
  16. #if defined(FE_SB)
  17. #ifdef IsDBCSLeadByte
  18. #undef IsDBCSLeadByte
  19. #define IsDBCSLeadByte(x) IsDBCSLeadByteEx(CP_ACP,x)
  20. #endif
  21. #endif
  22. /*
  23. * Most of the routines in this file will need to stay ANSI. If a UNICODE
  24. * version is needed, it is supplied.
  25. *
  26. * This is because for the most part, the information in the PIF files
  27. * is ANSI and needs to stay that way.
  28. *
  29. * (RickTu)
  30. *
  31. */
  32. /** lstrcpytrimA - copy fixed-length string, trimming trailing blanks
  33. *
  34. * INPUT
  35. * lpszDst -> destination string
  36. * lpszSrc -> fixed-length source string
  37. * cchMax = size (in characters) of fixed-length source string
  38. *
  39. * OUTPUT
  40. * Nothing
  41. */
  42. void lstrcpytrimA(LPSTR lpszDst, LPCSTR lpszSrc, int cchMax)
  43. {
  44. CHAR ch;
  45. int cchSave = 0;
  46. LPSTR lpszSave = lpszDst;
  47. FunctionName(lstrcpytrim);
  48. while (cchMax && *lpszSrc) {
  49. ch = *lpszSrc++;
  50. if (ch == ' ') {
  51. if (!cchSave) {
  52. cchSave = cchMax;
  53. lpszSave = lpszDst;
  54. }
  55. } else
  56. cchSave = 0;
  57. *lpszDst = ch;
  58. if (--cchMax) {
  59. lpszDst++;
  60. #if (defined(DBCS) || defined(FE_SB))
  61. if (IsDBCSLeadByte(ch) && --cchMax) {
  62. *lpszDst++ = *lpszSrc++;
  63. }
  64. #endif
  65. }
  66. }
  67. while (cchSave--)
  68. *lpszSave++ = '\0';
  69. *lpszDst = '\0';
  70. }
  71. /** lstrcpypadA - copy to fixed-length string, appending trailing blanks
  72. *
  73. * INPUT
  74. * lpszDst -> fixed-length destination string
  75. * lpszSrc -> source string
  76. * cchMax = size of fixed-length destination string (count of characters)
  77. *
  78. * OUTPUT
  79. * Nothing
  80. */
  81. void lstrcpypadA(LPSTR lpszDst, LPCSTR lpszSrc, int cchMax)
  82. {
  83. FunctionName(lstrcpypadA);
  84. while (cchMax && *lpszSrc) {
  85. cchMax--;
  86. *lpszDst++ = *lpszSrc++;
  87. }
  88. while (cchMax--) {
  89. *lpszDst++ = ' ';
  90. }
  91. }
  92. /** lstrcpyncharA - copy variable-length string, until char
  93. *
  94. * INPUT
  95. * lpszDst -> fixed-length destination string
  96. * lpszSrc -> source string
  97. * cchMax = size of fixed-length destination string (count of characters)
  98. * ch = character to stop copying at
  99. *
  100. * OUTPUT
  101. * # of characters copied, excluding terminating NULL
  102. */
  103. int lstrcpyncharA(LPSTR lpszDst, LPCSTR lpszSrc, int cchMax, CHAR ch)
  104. {
  105. int cch = 0;
  106. FunctionName(lstrcpyncharA);
  107. while (--cchMax && *lpszSrc && *lpszSrc != ch) {
  108. #if (defined(DBCS) || defined(FE_SB))
  109. if (IsDBCSLeadByte(*lpszSrc)) {
  110. cch++;
  111. *lpszDst++ = *lpszSrc++;
  112. if (!*lpszSrc) break; /* Eek! String ends in DBCS lead byte! */
  113. }
  114. #endif
  115. cch++;
  116. *lpszDst++ = *lpszSrc++;
  117. }
  118. *lpszDst = '\0';
  119. return cch;
  120. }
  121. /** lstrskipcharA - skip char in variable-length string
  122. *
  123. * INPUT
  124. * lpszSrc -> source string
  125. * ch = character to skip
  126. *
  127. * OUTPUT
  128. * # of characters skipped, 0 if none
  129. */
  130. int lstrskipcharA(LPCSTR lpszSrc, CHAR ch)
  131. {
  132. int cch = 0;
  133. FunctionName(lstrskipcharA);
  134. while (*lpszSrc && *lpszSrc == ch) {
  135. cch++;
  136. lpszSrc++;
  137. }
  138. return cch;
  139. }
  140. /** lstrskiptocharA - skip *to* char in variable-length string
  141. *
  142. * INPUT
  143. * lpszSrc -> source string
  144. * ch = character to skip *to*
  145. *
  146. * OUTPUT
  147. * # of characters skipped, 0 if none; if char didn't exist, then all
  148. * characters are skipped.
  149. */
  150. int lstrskiptocharA(LPCSTR lpszSrc, CHAR ch)
  151. {
  152. int cch = 0;
  153. FunctionName(lstrskiptocharA);
  154. while (*lpszSrc && *lpszSrc != ch) {
  155. cch++;
  156. lpszSrc++;
  157. }
  158. return cch;
  159. }
  160. /** lstrcpyfnameA - copy filename appropriately
  161. *
  162. * INPUT
  163. * lpszDst -> output buffer
  164. * lpszSrc -> source filename
  165. * cbMax = size of output buffer
  166. *
  167. * OUTPUT
  168. * # of characters copied, including quotes if any, excluding terminating NULL
  169. */
  170. int lstrcpyfnameA(LPSTR lpszDst, LPCSTR lpszSrc, int cchMax)
  171. {
  172. int cch;
  173. CHAR ch;
  174. FunctionName(lstrcpyfnameA);
  175. if (TEXT('\0') != (ch = lpszSrc[lstrskiptocharA(lpszSrc, ' ')])) {
  176. cchMax -= 2;
  177. *lpszDst++ = '\"';
  178. }
  179. lstrcpynA(lpszDst, lpszSrc, cchMax);
  180. cch = lstrlenA(lpszDst);
  181. if (ch) {
  182. lpszDst[cch++] = '\"';
  183. lpszDst[cch] = 0;
  184. }
  185. return cch;
  186. }
  187. /** lstrunquotefnameA - unquote filename if it contains quotes
  188. *
  189. * INPUT
  190. * lpszDst -> output buffer
  191. * lpszSrc -> source filename (quoted or unquoted)
  192. * cchMax = size of output buffer (count of characters)
  193. * fShort = TRUE if filename should be converted to 8.3 (eg, for real-mode);
  194. * -1 if the filename is known to not be quoted and should just be converted
  195. * OUTPUT
  196. * # of characters copied, excluding terminating NULL
  197. */
  198. int lstrunquotefnameA(LPSTR lpszDst, LPCSTR lpszSrc, int cchMax, BOOL fShort)
  199. {
  200. int cch;
  201. FunctionName(lstrunquotefnameA);
  202. if (fShort != -1) {
  203. if (lpszSrc[0] == '\"') {
  204. cch = lstrcpyncharA(lpszDst, lpszSrc+1, cchMax, '\"');
  205. }
  206. else {
  207. cch = lstrcpyncharA(lpszDst, lpszSrc, cchMax, ' ');
  208. }
  209. lpszSrc = lpszDst;
  210. }
  211. if (fShort) {
  212. cch = 1;
  213. CharToOemA(lpszSrc, lpszDst);
  214. cch = GetShortPathNameA( lpszSrc, lpszDst, cchMax );
  215. if (cch) { // if no error...
  216. if (fShort == TRUE) { // if conversion for real-mode...
  217. if ((int)GetFileAttributesA(lpszDst) == -1) {
  218. // if filename doesn't exist,
  219. // then just copy the 8.3 portion
  220. // and hope the user's real-mode PATH
  221. // ultimately finds it!
  222. if (NULL != (lpszSrc = StrRChrA(lpszDst, NULL, '\\'))) {
  223. lstrcpyA(lpszDst, lpszSrc+1);
  224. }
  225. }
  226. }
  227. cch = lstrlenA(lpszDst); // recompute the length of the string
  228. }
  229. }
  230. return cch;
  231. }
  232. /** lstrskipfnameA - skip filename in string
  233. *
  234. * INPUT
  235. * lpszSrc -> string beginning with filename (quoted or unquoted)
  236. *
  237. * OUTPUT
  238. * # of characters skipped, 0 if none
  239. */
  240. int lstrskipfnameA(LPCSTR lpszSrc)
  241. {
  242. int cch = 0;
  243. FunctionName(lstrskipfname);
  244. if (lpszSrc[0] == '\"') {
  245. cch = lstrskiptocharA(lpszSrc+1, '\"') + 1;
  246. if (lpszSrc[cch] == '\"')
  247. cch++;
  248. }
  249. else
  250. cch = lstrskiptocharA(lpszSrc, ' ');
  251. return cch;
  252. }
  253. /*
  254. * NOTE! The careful definitions of achBuf and achFmt, so that
  255. * we can support total output of 2 * MAX_STRING_SIZE bytes.
  256. */
  257. int cdecl Warning(HWND hwnd, WORD id, WORD type, ...)
  258. {
  259. LPCTSTR lpchFmt;
  260. PPROPLINK ppl = NULL;
  261. TCHAR achBuf[2*MAX_STRING_SIZE];
  262. #define achFmt (&achBuf[MAX_STRING_SIZE])
  263. va_list ArgList;
  264. FunctionName(Warning);
  265. lpchFmt = achFmt;
  266. // We never use MB_FOCUS to mean whatever it's really supposed
  267. // to mean; we just use it as a kludge to support warning dialogs
  268. // when all we have is a ppl, not an hwnd.
  269. if (type & MB_NOFOCUS) {
  270. ppl = (PPROPLINK)hwnd;
  271. hwnd = NULL;
  272. type &= ~MB_NOFOCUS;
  273. }
  274. else if (hwnd)
  275. ppl = ((PPROPLINK)GetWindowLongPtr(hwnd, DWLP_USER))->ppl;
  276. if (id == IDS_ERROR + ERROR_NOT_ENOUGH_MEMORY)
  277. lpchFmt = TEXT("");
  278. else {
  279. if (!LoadString(g_hinst, id, achFmt, MAX_STRING_SIZE)) {
  280. ASSERTFAIL();
  281. lpchFmt = TEXT("");
  282. }
  283. }
  284. va_start(ArgList,type);
  285. wvnsprintf(achBuf, MAX_STRING_SIZE, lpchFmt, ArgList);
  286. va_end(ArgList);
  287. lpchFmt = NULL;
  288. if (ppl) {
  289. ASSERTTRUE(ppl->iSig == PROP_SIG);
  290. if (!(lpchFmt = ppl->lpszTitle))
  291. lpchFmt = ppl->szPathName+ppl->iFileName;
  292. }
  293. return MessageBox(hwnd, achBuf, lpchFmt, type);
  294. }
  295. #undef achFmt
  296. int MemoryWarning(HWND hwnd)
  297. {
  298. FunctionName(MemoryWarning);
  299. return Warning(hwnd, IDS_ERROR + ERROR_NOT_ENOUGH_MEMORY, MB_ICONEXCLAMATION | MB_OK);
  300. }
  301. LPTSTR LoadStringSafe(HWND hwnd, UINT id, LPTSTR lpsz, int cchsz)
  302. {
  303. FunctionName(LoadStringSafe);
  304. if (!LoadString(g_hinst, id, lpsz, cchsz)) {
  305. ASSERTFAIL();
  306. if (hwnd) {
  307. MemoryWarning(hwnd);
  308. return NULL;
  309. }
  310. lpsz = TEXT("");
  311. }
  312. return lpsz;
  313. }
  314. /** SetDlgBits - Check various dialog checkboxes according to given flags
  315. *
  316. * INPUT
  317. * hDlg = HWND of dialog box
  318. * pbinf -> array of bitinfo descriptors
  319. * cbinf = size of array
  320. * wFlags = flags
  321. *
  322. * OUTPUT
  323. * Returns NOTHING
  324. */
  325. void SetDlgBits(HWND hDlg, PBINF pbinf, UINT cbinf, WORD wFlags)
  326. {
  327. FunctionName(SetDlgBits);
  328. ASSERTTRUE(cbinf > 0);
  329. do {
  330. ASSERTTRUE((pbinf->bBit & 0x3F) < 16);
  331. CheckDlgButton(hDlg, pbinf->id,
  332. !!(wFlags & (1 << (pbinf->bBit & 0x3F))) == !(pbinf->bBit & 0x80));
  333. } while (++pbinf, --cbinf);
  334. }
  335. /** GetDlgBits - Set various flags according to dialog checkboxes
  336. *
  337. * INPUT
  338. * hDlg = HWND of dialog box
  339. * pbinf -> array of bitinfo descriptors
  340. * cbinf = size of array
  341. * lpwFlags -> flags word
  342. *
  343. * OUTPUT
  344. * Returns NOTHING
  345. */
  346. void GetDlgBits(HWND hDlg, PBINF pbinf, UINT cbinf, LPWORD lpwFlags)
  347. {
  348. WORD wFlags;
  349. FunctionName(GetDlgBits);
  350. ASSERTTRUE(cbinf > 0);
  351. wFlags = *lpwFlags;
  352. do {
  353. ASSERTTRUE((pbinf->bBit & 0x3F) < 16);
  354. if (pbinf->bBit & 0x40) // 0x40 is a special bit mask
  355. continue; // that means "set but don't get
  356. // this control's value"
  357. wFlags &= ~(1 << (pbinf->bBit & 0x3F));
  358. if (!!IsDlgButtonChecked(hDlg, pbinf->id) == !(pbinf->bBit & 0x80))
  359. wFlags |= (1 << (pbinf->bBit & 0x3F));
  360. } while (++pbinf, --cbinf);
  361. *lpwFlags = wFlags;
  362. }
  363. /** SetDlgInts - Set various edit controls according to integer fields
  364. *
  365. * INPUT
  366. * hDlg = HWND of dialog box
  367. * pvinf -> array of validation info descriptors
  368. * cvinf = size of array
  369. * lp -> structure of integers
  370. *
  371. * OUTPUT
  372. * Returns NOTHING
  373. */
  374. void SetDlgInts(HWND hDlg, PVINF pvinf, UINT cvinf, LPVOID lp)
  375. {
  376. WORD wMin, wMax;
  377. FunctionName(SetDlgInts);
  378. ASSERTTRUE(cvinf > 0);
  379. do {
  380. wMin = wMax = *(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off);
  381. if (pvinf->fbOpt & VINF_AUTO) {
  382. SendDlgItemMessage(hDlg, pvinf->id, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)g_szAuto);
  383. AddDlgIntValues(hDlg, pvinf->id, pvinf->iMax);
  384. if (wMin == 0) {
  385. SetDlgItemText(hDlg, pvinf->id, g_szAuto);
  386. continue;
  387. }
  388. }
  389. if (pvinf->fbOpt & VINF_AUTOMINMAX) {
  390. SendDlgItemMessage(hDlg, pvinf->id, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)g_szAuto);
  391. SendDlgItemMessage(hDlg, pvinf->id, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)g_szNone);
  392. AddDlgIntValues(hDlg, pvinf->id, pvinf->iMax);
  393. // When AUTOMINMAX is set, we assume that the field
  394. // we're validating is followed in its structure by a
  395. // corresponding max WORD.
  396. wMax = *(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off + sizeof(WORD));
  397. if (wMin == 0 && wMax == 0) {
  398. SetDlgItemText(hDlg, pvinf->id, g_szNone);
  399. continue;
  400. }
  401. // Let's try to simplify things by mapping 0xFFFF (aka -1)
  402. // to settings that mean "Auto"
  403. if (wMin == 0xFFFF || wMax == 0xFFFF) {
  404. wMin = 0;
  405. wMax = (WORD)pvinf->iMax;
  406. }
  407. if (wMax == (WORD)pvinf->iMax) {
  408. SetDlgItemText(hDlg, pvinf->id, g_szAuto);
  409. continue;
  410. }
  411. if (wMin != wMax) {
  412. //
  413. // We're in a bit of a quandary here. The settings show
  414. // explicit min and max values which are not equal, probably
  415. // due to settings inherited from a 3.1 PIF file. We'll
  416. // just go with the wMax value. Fortunately for us, we
  417. // don't actually have to *do* anything to make this happen.
  418. //
  419. }
  420. }
  421. SetDlgItemInt(hDlg, pvinf->id, wMin, pvinf->iMin < 0);
  422. } while (++pvinf, --cvinf);
  423. }
  424. /** AddDlgIntValues - Fill integer combo-box with appropriate values
  425. *
  426. * INPUT
  427. * hDlg = HWND of dialog box
  428. * id = dialog control ID
  429. * iMax = maximum value
  430. *
  431. * OUTPUT
  432. * Returns NOTHING
  433. */
  434. void AddDlgIntValues(HWND hDlg, int id, int iMax)
  435. {
  436. int iStart, iInc;
  437. TCHAR achValue[16];
  438. // HACK to make this do something sensible with the environment max;
  439. // they can still enter larger values (up to ENVSIZE_MAX) but I don't
  440. // see any sense in encouraging it. -JTP
  441. if ((WORD)iMax == ENVSIZE_MAX)
  442. iMax = 4096;
  443. if ((iMax < 0) || (iMax == 0xFFFF)) // HACK to make this do something sensible
  444. iMax = 16384; // with fields that allow huge maximums -JTP
  445. iStart = iInc = iMax/16; // arbitrarily chop the range up 16 times
  446. while (iStart <= iMax) {
  447. wsprintf(achValue, TEXT("%d"), iStart);
  448. SendDlgItemMessage(hDlg, id, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)achValue);
  449. iStart += iInc;
  450. }
  451. }
  452. /** GetDlgInts - Set various integer fields according to dialog edit controls
  453. *
  454. * INPUT
  455. * hDlg = HWND of dialog box
  456. * pvinf -> array of validation info descriptors
  457. * cvinf = size of array
  458. * lp -> structure of integers
  459. *
  460. * OUTPUT
  461. * Returns NOTHING
  462. */
  463. void GetDlgInts(HWND hDlg, PVINF pvinf, int cvinf, LPVOID lp)
  464. {
  465. WORD wMin, wMax;
  466. UINT uTemp;
  467. BOOL fSuccess;
  468. TCHAR achText[32];
  469. FunctionName(GetDlgInts);
  470. ASSERTTRUE(cvinf > 0);
  471. do {
  472. uTemp = GetDlgItemInt(hDlg, pvinf->id, &fSuccess, pvinf->iMin < 0);
  473. ASSERT(HIWORD(uTemp)==0);
  474. wMin = LOWORD(uTemp);
  475. // In case of error, make sure wMin doesn't actually change
  476. if (!fSuccess)
  477. wMin = *(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off);
  478. if (pvinf->fbOpt & VINF_AUTO) {
  479. GetDlgItemText(hDlg, pvinf->id, achText, ARRAYSIZE(achText));
  480. if (lstrcmpi(achText, g_szAuto) == 0) {
  481. wMin = 0;
  482. }
  483. }
  484. if (pvinf->fbOpt & VINF_AUTOMINMAX) {
  485. // When AUTOMINMAX is set, we assume that the field
  486. // we're validating is followed in its structure by a
  487. // corresponding max WORD, which we will ZERO if the
  488. // user selects NONE, or set to its MAXIMUM if the user
  489. // selects AUTO, or otherwise set to match the specified
  490. // MINIMUM.
  491. wMax = wMin;
  492. GetDlgItemText(hDlg, pvinf->id, achText, ARRAYSIZE(achText));
  493. if (lstrcmpi(achText, g_szAuto) == 0) {
  494. wMin = 0;
  495. wMax = (WORD)pvinf->iMax;
  496. }
  497. else if (lstrcmpi(achText, g_szNone) == 0) {
  498. wMin = 0;
  499. wMax = 0;
  500. }
  501. *(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off + sizeof(WORD)) = wMax;
  502. }
  503. *(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off) = wMin;
  504. } while (++pvinf, --cvinf);
  505. }
  506. /** ValidateDlgInts - Validate that integer fields are value
  507. *
  508. * INPUT
  509. * hDlg = HWND of dialog box
  510. * pvinf -> array of validation descriptors
  511. * cvinf = size of array
  512. *
  513. * OUTPUT
  514. * Returns TRUE if something is wrong; FALSE if all is okay.
  515. */
  516. BOOL ValidateDlgInts(HWND hDlg, PVINF pvinf, int cvinf)
  517. {
  518. DWORD dw;
  519. BOOL fSuccess;
  520. TCHAR achText[32];
  521. FunctionName(ValidateDlgInts);
  522. ASSERTTRUE(cvinf > 0);
  523. do {
  524. dw = GetDlgItemInt(hDlg, pvinf->id, &fSuccess, pvinf->iMin < 0);
  525. // NOTE: AUTO is for "Auto" only, whereas AUTOMINMAX is for
  526. // "Auto" and "None". However, in the interest of simplicity, I
  527. // don't complain if either string is used in either case.
  528. if (pvinf->fbOpt & (VINF_AUTO | VINF_AUTOMINMAX)) {
  529. if (!fSuccess) {
  530. GetDlgItemText(hDlg, pvinf->id, achText, ARRAYSIZE(achText));
  531. if (lstrcmpi(achText, g_szNone) == 0 ||
  532. lstrcmpi(achText, g_szAuto) == 0) {
  533. continue; // things be lookin' good, check next int...
  534. }
  535. }
  536. }
  537. if (!fSuccess || dw < (DWORD)pvinf->iMin || dw > (DWORD)pvinf->iMax) {
  538. Warning(hDlg, pvinf->idMsg, MB_ICONEXCLAMATION | MB_OK, pvinf->iMin, pvinf->iMax);
  539. SendDlgItemMessage(hDlg, pvinf->id, EM_SETSEL, 0, MAKELPARAM(0,-1));
  540. SetFocus(GetDlgItem(hDlg, pvinf->id));
  541. return TRUE; // things be lookin' bad, bail out...
  542. }
  543. } while (++pvinf, --cvinf);
  544. return FALSE;
  545. }
  546. /*
  547. * NOTE -- The compiler emits really bad code for some of these guys.
  548. * In those cases, we are merely wrapping a call; there is no need to save BP.
  549. */
  550. /** LimitDlgItemText - Sets the limit for a dialog edit control
  551. *
  552. * INPUT
  553. * hDlg = HWND of dialog box
  554. * iCtl = ID of control
  555. * uiLimit = text limit
  556. *
  557. * OUTPUT
  558. * None.
  559. */
  560. void LimitDlgItemText(HWND hDlg, int iCtl, UINT uiLimit)
  561. {
  562. FunctionName(LimitDlgItemText);
  563. SendDlgItemMessage(hDlg, iCtl, EM_LIMITTEXT, uiLimit, 0);
  564. }
  565. /** SetDlgItemPosRange - Sets the pos and range for a dialog slider control
  566. *
  567. * INPUT
  568. * hDlg = HWND of dialog box
  569. * iCtl = ID of control
  570. * uiPos = Current position
  571. * dwRange = Range (min in low word, max in high word)
  572. *
  573. * OUTPUT
  574. * None.
  575. */
  576. void SetDlgItemPosRange(HWND hDlg, int iCtl, UINT uiPos, DWORD dwRange)
  577. {
  578. FunctionName(SetDlgItemPosRange);
  579. SendDlgItemMessage(hDlg, iCtl, TBM_SETRANGE, 0, dwRange);
  580. SendDlgItemMessage(hDlg, iCtl, TBM_SETPOS, TRUE, uiPos);
  581. }
  582. /** GetDlgItemPos - Gets the pos of a dialog slider control
  583. *
  584. * INPUT
  585. * hDlg = HWND of dialog box
  586. * iCtl = ID of control
  587. *
  588. * OUTPUT
  589. * Trackbar position.
  590. */
  591. UINT GetDlgItemPos(HWND hDlg, int iCtl)
  592. {
  593. FunctionName(GetDlgItemPos);
  594. return (UINT)SendDlgItemMessage(hDlg, iCtl, TBM_GETPOS, 0, 0);
  595. }
  596. /** SetDlgItemPct - Sets the pos for a dialog slider control that measures %
  597. *
  598. * INPUT
  599. * hDlg = HWND of dialog box
  600. * iCtl = ID of control
  601. * uiPct = Current position (range 0 .. 100)
  602. *
  603. * OUTPUT
  604. * None.
  605. */
  606. void SetDlgItemPct(HWND hDlg, int iCtl, UINT uiPct)
  607. {
  608. FunctionName(SetDlgItemPct);
  609. SetDlgItemPosRange(hDlg, iCtl, uiPct / (100/NUM_TICKS), MAKELONG(0, NUM_TICKS));
  610. }
  611. /** GetDlgItemPct - Gets the pos of a dialog slider control that measures %
  612. *
  613. * INPUT
  614. * hDlg = HWND of dialog box
  615. * iCtl = ID of control
  616. *
  617. * OUTPUT
  618. * Slider position in the range 0 .. 100.
  619. */
  620. UINT GetDlgItemPct(HWND hDlg, int iCtl)
  621. {
  622. FunctionName(GetDlgItemPct);
  623. return GetDlgItemPos(hDlg, iCtl) * (100/NUM_TICKS);
  624. }
  625. /** EnableDlgItems - Enables or disables a collection of dialog controls
  626. *
  627. * INPUT
  628. * hDlg = HWND of dialog box
  629. * pbinf -> array of bitinfo descriptors
  630. * cbinf = size of array
  631. * fEnable = whether the control should be enabled or disabled
  632. *
  633. * OUTPUT
  634. * Dialog items have changed state.
  635. */
  636. void EnableDlgItems(HWND hDlg, PBINF pbinf, int cbinf, BOOL fEnable)
  637. {
  638. FunctionName(EnableDlgItems);
  639. ASSERTTRUE(cbinf > 0);
  640. do {
  641. EnableWindow(GetDlgItem(hDlg, pbinf->id), fEnable);
  642. } while (++pbinf, --cbinf);
  643. }
  644. /** DisableDlgItems - Disables a collection of dialog controls
  645. *
  646. * Most of the time, we call EnableDlgItems with fEnable = TRUE, so
  647. * this is a handy wrapper. (Too bad the compiler emits awful code.)
  648. *
  649. * INPUT
  650. * hDlg = HWND of dialog box
  651. * pbinf -> array of bitinfo descriptors
  652. * cbinf = size of array
  653. *
  654. * OUTPUT
  655. * Dialog items have been disabled.
  656. */
  657. void DisableDlgItems(HWND hDlg, PBINF pbinf, int cbinf)
  658. {
  659. FunctionName(DisableDlgItems);
  660. EnableDlgItems(hDlg, pbinf, cbinf, 0);
  661. }
  662. /** AdjustRealModeControls - Disables selected items if single-app mode
  663. *
  664. * If the proplink says that "single-application mode" is enabled,
  665. * then hide all controls whose IDs are less than 4000 and show all
  666. * controls whose IDs are greater than or equal to 5000. Controls whose
  667. * IDs are in the 4000's are immune to all this hiding/showing. Controls
  668. * in the 3000's are actually disabled rather than hidden. Controls in
  669. * the 6000's are actually disabled rather than hidden as well.
  670. *
  671. * RST: Ok, this is nice in theory, but now that we've pulled over this
  672. * stuff into shell32.dll, we'll have to go off the actual IDC_
  673. * defines instead of the magic #'s of 3000, 4000 and 5000.
  674. *
  675. * IDC_ICONBMP == 3001
  676. * IDC_PIF_STATIC == 4000
  677. * IDC_REALMODEISABLE == 5001
  678. *
  679. * So, when adding things to shell232.rc or ids.h, plan
  680. * accordingly.
  681. *
  682. * INPUT
  683. * ppl = proplink
  684. * hDlg = HWND of dialog box
  685. *
  686. * OUTPUT
  687. * Dialog items have been disabled/enabled shown/hidden.
  688. * Returns nonzero if we are in normal (not single-app) mode.
  689. */
  690. BOOL CALLBACK EnableEnumProc(HWND hwnd, LPARAM lp)
  691. {
  692. int f;
  693. LONG l;
  694. f = SW_SHOW;
  695. l = GetWindowLong(hwnd, GWL_ID);
  696. if (!LOWORD(lp) && l < IDC_PIF_STATIC || LOWORD(lp) && l >= IDC_REALMODEDISABLE)
  697. f = SW_HIDE;
  698. if (l < IDC_ICONBMP || l >= IDC_PIF_STATIC && l < IDC_CONFIGLBL)
  699. ShowWindow(hwnd, f);
  700. else
  701. EnableWindow(hwnd, f == SW_SHOW);
  702. return TRUE;
  703. }
  704. BOOL AdjustRealModeControls(PPROPLINK ppl, HWND hDlg)
  705. {
  706. BOOL fNormal;
  707. FunctionName(AdjustRealModeControls);
  708. fNormal = !(ppl->flProp & PROP_REALMODE);
  709. EnumChildWindows(hDlg, EnableEnumProc, fNormal);
  710. return fNormal;
  711. }
  712. /** OnWmHelp - Handle a WM_HELP message
  713. *
  714. * This is called whenever the user presses F1 or clicks the help
  715. * button in the title bar. We forward the call on to the help engine.
  716. *
  717. * INPUT
  718. * lparam = LPARAM from WM_HELP message (LPHELPINFO)
  719. * pdwHelp = array of DWORDs of help info
  720. *
  721. * OUTPUT
  722. *
  723. * None.
  724. */
  725. void OnWmHelp(LPARAM lparam, const DWORD *pdwHelp)
  726. {
  727. FunctionName(OnWmHelp);
  728. WinHelp((HWND) ((LPHELPINFO) lparam)->hItemHandle, NULL,
  729. HELP_WM_HELP, (DWORD_PTR) (LPTSTR) pdwHelp);
  730. }
  731. /** OnWmContextMenu - Handle a WM_CONTEXTMENU message
  732. *
  733. * This is called whenever the user right-clicks on a control.
  734. * We forward the call on to the help engine.
  735. *
  736. * INPUT
  737. * wparam = WPARAM from WM_HELP message (HWND)
  738. * pdwHelp = array of DWORDs of help info
  739. *
  740. * OUTPUT
  741. *
  742. * None.
  743. */
  744. void OnWmContextMenu(WPARAM wparam, const DWORD *pdwHelp)
  745. {
  746. FunctionName(OnWmContextMenu);
  747. WinHelp((HWND) wparam, NULL, HELP_CONTEXTMENU,
  748. (DWORD_PTR) (LPTSTR) pdwHelp);
  749. }
  750. #ifdef UNICODE
  751. /** PifMgr_WCtoMBPath - Converts UNICODE path to it's ANSI representation
  752. *
  753. * This is called whenever we need to convert a UNICODE path to it's
  754. * best approximation in ANSI. Sometimes this will be a direct mapping,
  755. * but sometimes not. We may have to use the short name, etc.
  756. *
  757. * INPUT
  758. * lpUniPath -> pointer UNICODE path (NULL terminated)
  759. * lpAnsiPath -> pointer to buffer to hold ANSI path
  760. * cchBuf -> size of ANSI buffer, in characters
  761. *
  762. * OUTPUT
  763. *
  764. * lpAnsiPath buffer contains ANSI representation of lpUniPath
  765. */
  766. void PifMgr_WCtoMBPath(LPWSTR lpUniPath, LPSTR lpAnsiPath, UINT cchBuf )
  767. {
  768. WCHAR awchPath[ MAX_PATH ]; // Should be bigger than any PIF string
  769. CHAR achPath[ MAX_PATH ]; // Should be bigger than any PIF string
  770. UINT cchAnsi = 0;
  771. FunctionName(PifMgr_WCtoMBPath);
  772. // Try converting to Ansi and then converting back and comparing.
  773. // If we get back exactly what we started with, this is the "simple"
  774. // case.
  775. cchAnsi = WideCharToMultiByte( CP_ACP, 0,
  776. lpUniPath, -1,
  777. achPath, MAX_PATH,
  778. NULL, NULL );
  779. if (cchAnsi && (cchAnsi<=cchBuf)) {
  780. // Now try converting back
  781. MultiByteToWideChar( CP_ACP, 0,
  782. achPath, -1,
  783. awchPath, MAX_PATH
  784. );
  785. if (lstrcmp(lpUniPath,awchPath)==0) {
  786. // We're done...copy over the string.
  787. lstrcpynA( lpAnsiPath, achPath, cchBuf );
  788. *(BYTE UNALIGNED *)(lpAnsiPath+cchBuf-1) = '\0';
  789. return;
  790. }
  791. // Well, the string has some unmappable UNICODE
  792. // character in it, so try option #2 -- using the
  793. // short path name.
  794. goto TryShortPathName;
  795. } else {
  796. TryShortPathName:
  797. // Hmmm, the best we can do is to use the short path name and map
  798. // it to ANSI.
  799. GetShortPathName( lpUniPath, awchPath, MAX_PATH );
  800. awchPath[ MAX_PATH-1 ] = TEXT('\0');
  801. WideCharToMultiByte( CP_ACP, 0,
  802. awchPath, -1,
  803. lpAnsiPath, cchBuf,
  804. NULL, NULL
  805. );
  806. // Make sure we're NULL terminated
  807. *(BYTE UNALIGNED *)(lpAnsiPath+cchBuf-1) = '\0';
  808. }
  809. }
  810. #endif