Leaked source code of windows server 2003
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.

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