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.

1074 lines
30 KiB

  1. /*++
  2. Copyright (c) 1990-1998, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. dlgs.c
  5. Abstract:
  6. This module contains the common functions for the Win32 common dialogs.
  7. Revision History:
  8. --*/
  9. // precompiled headers
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #include "util.h"
  13. //
  14. // Global Variables.
  15. //
  16. extern BOOL bInitializing;
  17. extern DWORD g_tlsiExtError;
  18. //
  19. // Function Prototypes.
  20. //
  21. LONG
  22. RgbInvertRgb(
  23. LONG rgbOld);
  24. const struct _ERRORMAP
  25. {
  26. DWORD dwCommDlgError;
  27. DWORD dwWin32Error;
  28. } ERRORMAP[] =
  29. {
  30. { CDERR_INITIALIZATION , ERROR_INVALID_PARAMETER},
  31. { PDERR_INITFAILURE , ERROR_INVALID_PARAMETER},
  32. { CDERR_STRUCTSIZE , ERROR_INVALID_PARAMETER},
  33. { CDERR_NOTEMPLATE , ERROR_INVALID_PARAMETER},
  34. { CDERR_NOHINSTANCE , ERROR_INVALID_PARAMETER},
  35. { CDERR_NOHOOK , ERROR_INVALID_PARAMETER},
  36. { CDERR_MEMALLOCFAILURE , ERROR_OUTOFMEMORY},
  37. { CDERR_LOCKRESFAILURE , ERROR_INVALID_HANDLE},
  38. { CDERR_DIALOGFAILURE , E_FAIL},
  39. { PDERR_SETUPFAILURE , ERROR_INVALID_PARAMETER},
  40. { PDERR_RETDEFFAILURE , ERROR_INVALID_PARAMETER},
  41. { FNERR_BUFFERTOOSMALL , ERROR_INSUFFICIENT_BUFFER},
  42. { FRERR_BUFFERLENGTHZERO, ERROR_INSUFFICIENT_BUFFER},
  43. { FNERR_INVALIDFILENAME , ERROR_INVALID_NAME},
  44. { PDERR_NODEFAULTPRN , E_FAIL},
  45. { CFERR_NOFONTS , E_FAIL},
  46. { CFERR_MAXLESSTHANMIN , ERROR_INVALID_PARAMETER},
  47. };
  48. ////////////////////////////////////////////////////////////////////////////
  49. //
  50. // StoreExtendedError
  51. //
  52. // Stores an extended error code for the next call to
  53. // CommDlgExtendedError.
  54. //
  55. ////////////////////////////////////////////////////////////////////////////
  56. void StoreExtendedError(
  57. DWORD dwError)
  58. {
  59. int i;
  60. for (i=0; i < ARRAYSIZE(ERRORMAP); i++)
  61. {
  62. if (ERRORMAP[i].dwCommDlgError == dwError)
  63. {
  64. SetLastError(ERRORMAP[i].dwWin32Error);
  65. break;
  66. }
  67. }
  68. TlsSetValue(g_tlsiExtError, UlongToPtr(dwError));
  69. }
  70. ////////////////////////////////////////////////////////////////////////////
  71. //
  72. // GetStoredExtendedError
  73. //
  74. // Retieves the stored extended error code.
  75. //
  76. ////////////////////////////////////////////////////////////////////////////
  77. DWORD GetStoredExtendedError(void)
  78. {
  79. DWORD dwError;
  80. dwError = PtrToUlong(TlsGetValue(g_tlsiExtError));
  81. return (dwError);
  82. }
  83. ////////////////////////////////////////////////////////////////////////////
  84. //
  85. // CommDlgExtendedError
  86. //
  87. // Provides additional information about dialog failure.
  88. // This should be called immediately after failure.
  89. //
  90. // Returns: LO word - error code
  91. // HI word - error specific info
  92. //
  93. ////////////////////////////////////////////////////////////////////////////
  94. DWORD WINAPI CommDlgExtendedError()
  95. {
  96. return (GetStoredExtendedError());
  97. }
  98. ////////////////////////////////////////////////////////////////////////////
  99. //
  100. // HourGlass
  101. //
  102. // Turn hourglass on or off.
  103. //
  104. // bOn - specifies ON or OFF
  105. //
  106. ////////////////////////////////////////////////////////////////////////////
  107. VOID HourGlass(
  108. BOOL bOn)
  109. {
  110. //
  111. // Change cursor to hourglass.
  112. //
  113. if (!bInitializing)
  114. {
  115. if (!bMouse)
  116. {
  117. ShowCursor(bCursorLock = bOn);
  118. }
  119. SetCursor(LoadCursor(NULL, bOn ? IDC_WAIT : IDC_ARROW));
  120. }
  121. }
  122. ////////////////////////////////////////////////////////////////////////////
  123. //
  124. // LoadAlterBitmap
  125. //
  126. // Loads a bitmap given its name and gives all the pixels that are
  127. // a certain color a new color.
  128. //
  129. // Returns: NULL - failed
  130. // handle to the bitmap loaded - success
  131. //
  132. ////////////////////////////////////////////////////////////////////////////
  133. HBITMAP WINAPI LoadAlterBitmap(
  134. int id,
  135. DWORD rgbReplace,
  136. DWORD rgbInstead)
  137. {
  138. LPBITMAPINFOHEADER qbihInfo;
  139. HDC hdcScreen;
  140. BOOL fFound;
  141. HANDLE hresLoad;
  142. HANDLE hres;
  143. LPLONG qlng;
  144. DWORD *qlngReplace; // points to bits that are replaced
  145. LPBYTE qbBits;
  146. HANDLE hbmp;
  147. LPBITMAPINFOHEADER lpBitmapInfo;
  148. UINT cbBitmapSize;
  149. hresLoad = FindResource(g_hinst, MAKEINTRESOURCE(id), RT_BITMAP);
  150. if (hresLoad == HNULL)
  151. {
  152. return (HNULL);
  153. }
  154. hres = LoadResource(g_hinst, hresLoad);
  155. if (hres == HNULL)
  156. {
  157. return (HNULL);
  158. }
  159. //
  160. // Lock the bitmap data and make a copy of it for the mask and the
  161. // bitmap.
  162. //
  163. cbBitmapSize = SizeofResource(g_hinst, hresLoad);
  164. lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hres);
  165. qbihInfo = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, cbBitmapSize);
  166. if ((lpBitmapInfo == NULL) || (qbihInfo == NULL))
  167. {
  168. return (NULL);
  169. }
  170. memcpy((TCHAR *)qbihInfo, (TCHAR *)lpBitmapInfo, cbBitmapSize);
  171. //
  172. // Get a pointer into the color table of the bitmaps, cache the
  173. // number of bits per pixel.
  174. //
  175. rgbReplace = RgbInvertRgb(rgbReplace);
  176. rgbInstead = RgbInvertRgb(rgbInstead);
  177. qlng = (LPLONG)((LPSTR)(qbihInfo) + qbihInfo->biSize);
  178. fFound = FALSE;
  179. while (!fFound)
  180. {
  181. if (*qlng == (LONG)rgbReplace)
  182. {
  183. fFound = TRUE;
  184. qlngReplace = (DWORD *)qlng;
  185. *qlng = (LONG)rgbInstead;
  186. }
  187. qlng++;
  188. }
  189. //
  190. // First skip over the header structure.
  191. //
  192. qbBits = (LPBYTE)(qbihInfo + 1);
  193. //
  194. // Skip the color table entries, if any.
  195. //
  196. qbBits += (1 << (qbihInfo->biBitCount)) * sizeof(RGBQUAD);
  197. //
  198. // Create a color bitmap compatible with the display device.
  199. //
  200. hdcScreen = GetDC(HNULL);
  201. if (hdcScreen != HNULL)
  202. {
  203. hbmp = CreateDIBitmap( hdcScreen,
  204. qbihInfo,
  205. (LONG)CBM_INIT,
  206. qbBits,
  207. (LPBITMAPINFO)qbihInfo,
  208. DIB_RGB_COLORS );
  209. ReleaseDC(HNULL, hdcScreen);
  210. }
  211. //
  212. // Reset color bits to original value.
  213. //
  214. *qlngReplace = (LONG)rgbReplace;
  215. LocalFree(qbihInfo);
  216. return (hbmp);
  217. }
  218. ////////////////////////////////////////////////////////////////////////////
  219. //
  220. // RgbInvertRgb
  221. //
  222. // Reverses the byte order of the RGB value (for file format).
  223. //
  224. // Returns the new color value (RGB to BGR).
  225. //
  226. ////////////////////////////////////////////////////////////////////////////
  227. LONG RgbInvertRgb(
  228. LONG rgbOld)
  229. {
  230. LONG lRet;
  231. BYTE R, G, B;
  232. R = GetRValue(rgbOld);
  233. G = GetGValue(rgbOld);
  234. B = GetBValue(rgbOld);
  235. lRet = (LONG)RGB(B, G, R);
  236. return (lRet);
  237. }
  238. ////////////////////////////////////////////////////////////////////////////
  239. //
  240. // HbmpLoadBmp
  241. //
  242. // Loads in a bitmap.
  243. //
  244. // Returns: Bitmap handle - success
  245. // HNULL - failure
  246. //
  247. ////////////////////////////////////////////////////////////////////////////
  248. #if 0
  249. HBITMAP HbmpLoadBmp(
  250. WORD bmp)
  251. {
  252. HBITMAP hbmp;
  253. CHAR szBitmap[cbResNameMax];
  254. hbmp = HNULL;
  255. if (LoadString(g_hinst, bmp, (LPTSTR)szBitmap, cbResNameMax - 1))
  256. {
  257. hbmp = LoadBitmap(g_hinst, (LPCTSTR)szBitmap);
  258. }
  259. return (hbmp);
  260. }
  261. #endif
  262. ////////////////////////////////////////////////////////////////////////////
  263. //
  264. // AddNetButton
  265. //
  266. // Attempts to add a network button to the open, save, or print dialogs.
  267. //
  268. // hDlg - dialog to add button to
  269. // hInstance - instance handle for dlg
  270. // dyBottomMargin - DUs to bottom edge
  271. //
  272. ////////////////////////////////////////////////////////////////////////////
  273. #define xDUsToPels(DUs, lDlgBaseUnits) \
  274. (int)(((DUs) * (int)LOWORD((lDlgBaseUnits))) / 4)
  275. #define yDUsToPels(DUs, lDlgBaseUnits) \
  276. (int)(((DUs) * (int)HIWORD((lDlgBaseUnits))) / 8)
  277. VOID AddNetButton(
  278. HWND hDlg,
  279. HANDLE hInstance,
  280. int dyBottomMargin,
  281. BOOL bAddAccel,
  282. BOOL bTryLowerRight,
  283. BOOL bTryLowerLeft)
  284. {
  285. LONG lDlgBaseUnits;
  286. RECT rcDlg, rcCtrl, rcTmp;
  287. LONG xButton, yButton;
  288. LONG dxButton, dyButton;
  289. LONG dxDlgFrame, dyDlgFrame;
  290. LONG yDlgHeight, xDlgWidth;
  291. HWND hwndButton, hCtrl, hLastCtrl, hTmp, hSave;
  292. HFONT hFont;
  293. POINT ptTopLeft, ptTopRight, ptCenter, ptBtmLeft, ptBtmRight, ptTopLeftTmp;
  294. TCHAR szNetwork[MAX_PATH];
  295. //
  296. // Make sure a network button (psh14) doesn't already exist in
  297. // the dialog.
  298. //
  299. if (GetDlgItem(hDlg, psh14))
  300. {
  301. return;
  302. }
  303. //
  304. // Get dialog coordinate info.
  305. //
  306. lDlgBaseUnits = GetDialogBaseUnits();
  307. dxDlgFrame = GetSystemMetrics(SM_CXDLGFRAME);
  308. dyDlgFrame = GetSystemMetrics(SM_CYDLGFRAME);
  309. GetWindowRect(hDlg, &rcDlg);
  310. rcDlg.left += dxDlgFrame;
  311. rcDlg.right -= dxDlgFrame;
  312. rcDlg.top += dyDlgFrame + GetSystemMetrics(SM_CYCAPTION);
  313. rcDlg.bottom -= dyDlgFrame;
  314. //
  315. // Get the OK button.
  316. //
  317. if (!(hCtrl = GetDlgItem(hDlg, IDOK)))
  318. {
  319. return;
  320. }
  321. GetWindowRect(hCtrl, &rcCtrl);
  322. ptTopLeft.x = rcCtrl.left;
  323. ptTopLeft.y = rcCtrl.top;
  324. //
  325. // Make sure the OK button isn't outside the dialog.
  326. //
  327. if (!PtInRect(&rcDlg, ptTopLeft))
  328. {
  329. //
  330. // Try the CANCEL button.
  331. //
  332. if (!(hCtrl = GetDlgItem(hDlg, IDCANCEL)))
  333. {
  334. //
  335. // Both OK and CANCEL do not exist, so return.
  336. //
  337. return;
  338. }
  339. //
  340. // The check for the Cancel button outside the dialog is handled
  341. // below.
  342. //
  343. GetWindowRect(hCtrl, &rcCtrl);
  344. }
  345. hSave = hCtrl;
  346. #ifdef UNICODE
  347. //
  348. // Get the full hDlg value if coming from WOW.
  349. //
  350. if (IS_INTRESOURCE(hDlg))
  351. {
  352. HWND hNewDlg = GetParent(hCtrl);
  353. if (hDlg == (HWND)LOWORD(hNewDlg))
  354. {
  355. hDlg = hNewDlg;
  356. }
  357. }
  358. #endif
  359. //
  360. // Save the coordinate info of the button.
  361. //
  362. dxButton = rcCtrl.right - rcCtrl.left;
  363. dyButton = rcCtrl.bottom - rcCtrl.top;
  364. xButton = rcCtrl.left;
  365. yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits);
  366. yDlgHeight = rcDlg.bottom - yDUsToPels(dyBottomMargin, lDlgBaseUnits);
  367. //
  368. // Try to insert the network button in the lower right corner
  369. // of dialog box.
  370. //
  371. if (bTryLowerRight && (hTmp = GetDlgItem(hDlg, cmb2)))
  372. {
  373. //
  374. // See if the network button can be inserted in the
  375. // lower right corner of the dialog box.
  376. //
  377. hLastCtrl = hCtrl;
  378. GetWindowRect(hTmp, &rcTmp);
  379. yButton = rcTmp.top;
  380. //
  381. // Set the coordinates of the new button.
  382. //
  383. ptTopLeft.x = ptBtmLeft.x = xButton;
  384. ptTopLeft.y = ptTopRight.y = yButton;
  385. ptTopRight.x = ptBtmRight.x = xButton + dxButton;
  386. ptBtmLeft.y = ptBtmRight.y = yButton + dyButton;
  387. ptCenter.x = xButton + dxButton / 2;
  388. ptCenter.y = yButton + dyButton / 2;
  389. ScreenToClient(hDlg, (LPPOINT)&ptTopLeft);
  390. ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft);
  391. ScreenToClient(hDlg, (LPPOINT)&ptTopRight);
  392. ScreenToClient(hDlg, (LPPOINT)&ptBtmRight);
  393. ScreenToClient(hDlg, (LPPOINT)&ptCenter);
  394. //
  395. // See if the new button is over any other buttons.
  396. //
  397. if (((yButton + dyButton) < yDlgHeight) &&
  398. ((ChildWindowFromPoint(hDlg, ptTopLeft) == hDlg) &&
  399. (ChildWindowFromPoint(hDlg, ptTopRight) == hDlg) &&
  400. (ChildWindowFromPoint(hDlg, ptCenter) == hDlg) &&
  401. (ChildWindowFromPoint(hDlg, ptBtmLeft) == hDlg) &&
  402. (ChildWindowFromPoint(hDlg, ptBtmRight) == hDlg)))
  403. {
  404. //
  405. // If the last control is the OK button and there is a
  406. // HELP button, then the last control should be the
  407. // HELP button.
  408. //
  409. if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) &&
  410. (hCtrl = GetDlgItem(hDlg, pshHelp)))
  411. {
  412. GetWindowRect(hCtrl, &rcCtrl);
  413. ptTopLeftTmp.x = rcCtrl.left;
  414. ptTopLeftTmp.y = rcCtrl.top;
  415. //
  416. // Make sure the HELP button isn't outside the dialog
  417. // and then set the last control to be the HELP button.
  418. //
  419. if (PtInRect(&rcDlg, ptTopLeftTmp))
  420. {
  421. hLastCtrl = hCtrl;
  422. }
  423. }
  424. //
  425. // If the last control is still the OK button and there is a
  426. // CANCEL button, then the last control should be the
  427. // CANCEL button.
  428. //
  429. if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) &&
  430. (hCtrl = GetDlgItem(hDlg, IDCANCEL)))
  431. {
  432. GetWindowRect(hCtrl, &rcCtrl);
  433. ptTopLeftTmp.x = rcCtrl.left;
  434. ptTopLeftTmp.y = rcCtrl.top;
  435. //
  436. // Make sure the CANCEL button isn't outside the dialog
  437. // and then set the last control to be the CANCEL button.
  438. //
  439. if (PtInRect(&rcDlg, ptTopLeftTmp))
  440. {
  441. hLastCtrl = hCtrl;
  442. }
  443. }
  444. goto FoundPlace;
  445. }
  446. //
  447. // Reset yButton.
  448. //
  449. yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits);
  450. }
  451. //
  452. // Try to insert the network button vertically below the other
  453. // control buttons.
  454. //
  455. while (hCtrl != NULL)
  456. {
  457. //
  458. // Move vertically down and see if there is space.
  459. //
  460. hLastCtrl = hCtrl;
  461. GetWindowRect(hCtrl, &rcCtrl);
  462. yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits);
  463. //
  464. // Make sure there is still room in the dialog.
  465. //
  466. if ((yButton + dyButton) > yDlgHeight)
  467. {
  468. //
  469. // No space.
  470. //
  471. break;
  472. }
  473. //
  474. // Set the coordinates of the new button.
  475. //
  476. ptTopLeft.x = ptBtmLeft.x = xButton;
  477. ptTopLeft.y = ptTopRight.y = yButton;
  478. ptTopRight.x = ptBtmRight.x = xButton + dxButton;
  479. ptBtmLeft.y = ptBtmRight.y = yButton + dyButton;
  480. ptCenter.x = xButton + dxButton / 2;
  481. ptCenter.y = yButton + dyButton / 2;
  482. ScreenToClient(hDlg, (LPPOINT)&ptTopLeft);
  483. ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft);
  484. ScreenToClient(hDlg, (LPPOINT)&ptTopRight);
  485. ScreenToClient(hDlg, (LPPOINT)&ptBtmRight);
  486. ScreenToClient(hDlg, (LPPOINT)&ptCenter);
  487. //
  488. // See if the new button is over any other buttons.
  489. //
  490. if (((hCtrl = ChildWindowFromPoint(hDlg, ptTopLeft)) == hDlg) &&
  491. ((hCtrl = ChildWindowFromPoint(hDlg, ptTopRight)) == hDlg) &&
  492. ((hCtrl = ChildWindowFromPoint(hDlg, ptCenter)) == hDlg) &&
  493. ((hCtrl = ChildWindowFromPoint(hDlg, ptBtmLeft)) == hDlg) &&
  494. ((hCtrl = ChildWindowFromPoint(hDlg, ptBtmRight)) == hDlg))
  495. {
  496. goto FoundPlace;
  497. }
  498. }
  499. //
  500. // Try to insert the network button in the lower left corner of
  501. // the dialog box.
  502. //
  503. if (bTryLowerLeft)
  504. {
  505. //
  506. // Get the width of the dialog to make sure the button doesn't
  507. // go off the side of the dialog.
  508. //
  509. xDlgWidth = rcDlg.right - xDUsToPels(FILE_RIGHT_MARGIN, lDlgBaseUnits);
  510. //
  511. // Use the OK or CANCEL button saved earlier to get the size of
  512. // the buttons.
  513. //
  514. hCtrl = hSave;
  515. //
  516. // Start at the far left of the dialog.
  517. //
  518. // NOTE: We know that hCtrl is not NULL at this point because
  519. // otherwise we would have returned earlier.
  520. //
  521. // The print dialogs have a left margin of 8.
  522. //
  523. GetWindowRect(hCtrl, &rcCtrl);
  524. xButton = rcDlg.left + xDUsToPels(FILE_LEFT_MARGIN + 3, lDlgBaseUnits);
  525. yButton = rcCtrl.top;
  526. while (1)
  527. {
  528. hLastCtrl = hCtrl;
  529. //
  530. // Make sure there is still room in the dialog.
  531. //
  532. if ((xButton + dxButton) > xDlgWidth)
  533. {
  534. //
  535. // No space.
  536. //
  537. break;
  538. }
  539. //
  540. // Set the coordinates of the new button.
  541. //
  542. ptTopLeft.x = ptBtmLeft.x = xButton;
  543. ptTopLeft.y = ptTopRight.y = yButton;
  544. ptTopRight.x = ptBtmRight.x = xButton + dxButton;
  545. ptBtmLeft.y = ptBtmRight.y = yButton + dyButton;
  546. ptCenter.x = xButton + dxButton / 2;
  547. ptCenter.y = yButton + dyButton / 2;
  548. ScreenToClient(hDlg, (LPPOINT)&ptTopLeft);
  549. ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft);
  550. ScreenToClient(hDlg, (LPPOINT)&ptTopRight);
  551. ScreenToClient(hDlg, (LPPOINT)&ptBtmRight);
  552. ScreenToClient(hDlg, (LPPOINT)&ptCenter);
  553. //
  554. // See if the new button is over any other buttons.
  555. //
  556. if ( ( ((hCtrl = ChildWindowFromPoint(hDlg, ptTopLeft)) == hDlg) &&
  557. ((hCtrl = ChildWindowFromPoint(hDlg, ptTopRight)) == hDlg) &&
  558. ((hCtrl = ChildWindowFromPoint(hDlg, ptCenter)) == hDlg) &&
  559. ((hCtrl = ChildWindowFromPoint(hDlg, ptBtmLeft)) == hDlg) &&
  560. ((hCtrl = ChildWindowFromPoint(hDlg, ptBtmRight)) == hDlg) ) )
  561. {
  562. //
  563. // If the last control is the OK button and there is a
  564. // HELP button, then the last control should be the
  565. // HELP button.
  566. //
  567. if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) &&
  568. (hCtrl = GetDlgItem(hDlg, pshHelp)))
  569. {
  570. GetWindowRect(hCtrl, &rcCtrl);
  571. ptTopLeftTmp.x = rcCtrl.left;
  572. ptTopLeftTmp.y = rcCtrl.top;
  573. //
  574. // Make sure the HELP button isn't outside the dialog
  575. // and then set the last control to be the HELP button.
  576. //
  577. if (PtInRect(&rcDlg, ptTopLeftTmp))
  578. {
  579. hLastCtrl = hCtrl;
  580. }
  581. }
  582. //
  583. // If the last control is still the OK button and there is a
  584. // CANCEL button, then the last control should be the
  585. // CANCEL button.
  586. //
  587. if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) &&
  588. (hCtrl = GetDlgItem(hDlg, IDCANCEL)))
  589. {
  590. GetWindowRect(hCtrl, &rcCtrl);
  591. ptTopLeftTmp.x = rcCtrl.left;
  592. ptTopLeftTmp.y = rcCtrl.top;
  593. //
  594. // Make sure the CANCEL button isn't outside the dialog
  595. // and then set the last control to be the CANCEL button.
  596. //
  597. if (PtInRect(&rcDlg, ptTopLeftTmp))
  598. {
  599. hLastCtrl = hCtrl;
  600. }
  601. }
  602. goto FoundPlace;
  603. }
  604. //
  605. // Make sure we encountered another control and that we
  606. // didn't go off the end of the dialog.
  607. //
  608. if (!hCtrl)
  609. {
  610. break;
  611. }
  612. //
  613. // Move over to the right and see if there is space.
  614. //
  615. GetWindowRect(hCtrl, &rcCtrl);
  616. xButton = rcCtrl.right + xDUsToPels(4, lDlgBaseUnits);
  617. }
  618. }
  619. return;
  620. FoundPlace:
  621. xButton = ptTopLeft.x;
  622. yButton = ptTopLeft.y;
  623. //If it a mirrored Dlg then the direction will be to the right.
  624. if (IS_WINDOW_RTL_MIRRORED(hDlg))
  625. xButton -= dxButton;
  626. if (CDLoadString( g_hinst,
  627. (bAddAccel ? iszNetworkButtonTextAccel : iszNetworkButtonText),
  628. (LPTSTR)szNetwork,
  629. MAX_PATH ))
  630. {
  631. hwndButton = CreateWindow( TEXT("button"),
  632. szNetwork,
  633. WS_VISIBLE | WS_CHILD | WS_GROUP |
  634. WS_TABSTOP | BS_PUSHBUTTON,
  635. xButton,
  636. yButton,
  637. dxButton,
  638. dyButton,
  639. hDlg,
  640. NULL,
  641. hInstance,
  642. NULL );
  643. if (hwndButton != NULL)
  644. {
  645. SetWindowLong(hwndButton, GWL_ID, psh14);
  646. SetWindowPos( hwndButton,
  647. hLastCtrl,
  648. 0, 0, 0, 0,
  649. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
  650. hFont = (HFONT)SendDlgItemMessage(hDlg, IDOK, WM_GETFONT, 0, 0L);
  651. SendMessage(hwndButton, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE,0));
  652. }
  653. }
  654. }
  655. ////////////////////////////////////////////////////////////////////////////
  656. //
  657. // IsNetworkInstalled
  658. //
  659. ////////////////////////////////////////////////////////////////////////////
  660. BOOL IsNetworkInstalled()
  661. {
  662. if (GetSystemMetrics(SM_NETWORK) & RNC_NETWORKS)
  663. {
  664. return (TRUE);
  665. }
  666. else
  667. {
  668. return (FALSE);
  669. }
  670. }
  671. #ifdef WINNT
  672. ////////////////////////////////////////////////////////////////////////////
  673. //
  674. // Ssync_ANSI_UNICODE_Struct_For_WOW (This is exported for WOW)
  675. //
  676. // For WOW support on NT only.
  677. //
  678. // When a 16-bit app calls one of the comdlg API's, WOW thunks the 16-bit
  679. // comdlg struct passed by the app to a 32-bit ANSI struct. Comdlg32 code
  680. // then thunks the 32-bit ANSI struct into a UNICODE struct. This scheme
  681. // creates a problem for WOW apps because on Win3.1, the app and comdlg16
  682. // share the same structure. When either updates the struct, the other is
  683. // aware of the change.
  684. //
  685. // This function allows us to sychronize the UNICODE struct with the app's
  686. // 16-bit struct & vice versa from WOW.
  687. //
  688. ////////////////////////////////////////////////////////////////////////////
  689. VOID Ssync_ANSI_UNICODE_Struct_For_WOW(
  690. HWND hDlg,
  691. BOOL fDirection,
  692. DWORD dwID)
  693. {
  694. switch (dwID)
  695. {
  696. case ( WOW_CHOOSECOLOR ) :
  697. {
  698. Ssync_ANSI_UNICODE_CC_For_WOW(hDlg, fDirection);
  699. break;
  700. }
  701. case ( WOW_CHOOSEFONT ) :
  702. {
  703. Ssync_ANSI_UNICODE_CF_For_WOW(hDlg, fDirection);
  704. break;
  705. }
  706. case ( WOW_OPENFILENAME ) :
  707. {
  708. Ssync_ANSI_UNICODE_OFN_For_WOW(hDlg, fDirection);
  709. break;
  710. }
  711. case ( WOW_PRINTDLG ) :
  712. {
  713. Ssync_ANSI_UNICODE_PD_For_WOW(hDlg, fDirection);
  714. break;
  715. }
  716. // case not needed for FINDREPLACE
  717. }
  718. }
  719. #endif
  720. #ifdef WX86
  721. ////////////////////////////////////////////////////////////////////////////
  722. //
  723. // Wx86GetX86Callback
  724. //
  725. // Creates a RISC-callable alias for a x86 hook function pointer.
  726. //
  727. // lpfnHook - x86 address of hook
  728. //
  729. // Returns a function pointer which can be called from RISC.
  730. //
  731. ////////////////////////////////////////////////////////////////////////////
  732. PVOID Wx86GetX86Callback(
  733. PVOID lpfnHook)
  734. {
  735. if (!lpfnHook)
  736. {
  737. return (NULL);
  738. }
  739. if (!pfnAllocCallBx86)
  740. {
  741. HMODULE hMod;
  742. if (!Wx86CurrentTib())
  743. {
  744. //
  745. // Wx86 is not running in this thread. Assume a RISC app has
  746. // passed a bad flag value and that lpfnHook is already a RISC
  747. // function pointer.
  748. //
  749. return (lpfnHook);
  750. }
  751. hMod = GetModuleHandle(TEXT("wx86.dll"));
  752. if (hMod == NULL)
  753. {
  754. //
  755. // Wx86 is running, but wx86.dll is not loaded! This should
  756. // never happen, but if it does, assume lpfnHook is already a
  757. // RISC pointer.
  758. //
  759. return (lpfnHook);
  760. }
  761. pfnAllocCallBx86 = (PALLOCCALLBX86)GetProcAddress( hMod,
  762. "AllocCallBx86" );
  763. if (!pfnAllocCallBx86)
  764. {
  765. //
  766. // Something has gone terribly wrong!
  767. //
  768. return (lpfnHook);
  769. }
  770. }
  771. //
  772. // Call into Wx86.dll to create a RISC-to-x86 callback which takes
  773. // 4 parameters and has no logging.
  774. //
  775. return (*pfnAllocCallBx86)(lpfnHook, 4, NULL, NULL);
  776. }
  777. #endif
  778. ////////////////////////////////////////////////////////////////////////////
  779. //
  780. // CDLoadString
  781. //
  782. ////////////////////////////////////////////////////////////////////////////
  783. int CDLoadString(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax)
  784. {
  785. return CDLoadStringEx(CP_ACP, hInstance, uID, lpBuffer, nBufferMax);
  786. }
  787. // CDLoadStringEx takes a codepage, so we can store unicode strings in the resource file
  788. int CDLoadStringEx(UINT cp, HINSTANCE hInstance, UINT uID, LPTSTR pszBuffer, int nBufferMax)
  789. {
  790. HRSRC hResInfo;
  791. int cch = 0;
  792. LPWSTR lpwsz;
  793. LANGID LangID;
  794. if (!GET_BIDI_LOCALIZED_SYSTEM_LANGID(NULL))
  795. {
  796. return LoadString(hInstance, uID, pszBuffer, nBufferMax);
  797. }
  798. LangID = (LANGID)TlsGetValue(g_tlsLangID);
  799. if (!LangID || MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) == LangID) {
  800. return LoadString(hInstance, uID, pszBuffer, nBufferMax);
  801. }
  802. if (!pszBuffer || (nBufferMax-- == 0))
  803. return 0;
  804. // String Tables are broken up into 16 string resources. Find the resource
  805. // containing the string we are interested in.
  806. if (hResInfo = FindResourceExFallback(hInstance, RT_STRING, MAKEINTRESOURCE((uID>>4)+1), LangID)) {
  807. // Load the resource. Note LoadResource returns an address.
  808. if (lpwsz = (LPWSTR)LoadResource(hInstance, hResInfo)) {
  809. // Move past the other strings in this resource.
  810. // (16 strings in a segment -> & 0x0F)
  811. for (uID %= 16; uID; uID--) {
  812. lpwsz += *lpwsz + 1;
  813. }
  814. cch = min(*lpwsz, nBufferMax - 1);
  815. // Copy the string into the buffer;
  816. memcpy(pszBuffer, lpwsz+1, cch*sizeof(WCHAR));
  817. }
  818. }
  819. pszBuffer[cch] = 0;
  820. return cch;
  821. }
  822. #define ENGLISH_APP 0
  823. #define MIRRORED_APP 1
  824. #define BIDI_APP 2
  825. DWORD GetAppType(HWND hWnd) {
  826. DWORD dwExStyle = 0;
  827. HWND hWndT = hWnd;
  828. DWORD dwAppType = ENGLISH_APP;
  829. #ifdef CHECK_OWNER
  830. //Check the window and its owners.
  831. while (!dwExStyle && hWndT) {
  832. dwExStyle = GetWindowLongA(hWndT, GWL_EXSTYLE) & (WS_EX_RIGHT | WS_EX_RTLREADING | RTL_MIRRORED_WINDOW);
  833. hWndT = GetWindow(hWndT, GW_OWNER);
  834. }
  835. if (!dwExStyle) {
  836. #endif
  837. //If we still did not find then check the parents.
  838. hWndT = hWnd;
  839. while (!dwExStyle && hWndT) {
  840. dwExStyle = GetWindowLongA(hWndT, GWL_EXSTYLE) & (WS_EX_RIGHT | WS_EX_RTLREADING | RTL_MIRRORED_WINDOW);
  841. hWndT = GetParent(hWndT);
  842. }
  843. #ifdef CHECK_OWNER
  844. }
  845. #endif
  846. if (dwExStyle & RTL_MIRRORED_WINDOW) {
  847. dwAppType = MIRRORED_APP;
  848. } else if (dwExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING)) {
  849. dwAppType = BIDI_APP;
  850. }
  851. return dwAppType;
  852. }
  853. DWORD GetTemplateType(HANDLE hDlgTemplate)
  854. {
  855. DWORD dwExStyle = 0;
  856. DWORD dwAppType = ENGLISH_APP;
  857. LPDLGTEMPLATE pDlgTemplate;
  858. pDlgTemplate = (LPDLGTEMPLATE)LockResource(hDlgTemplate);
  859. if (pDlgTemplate) {
  860. if (((LPDLGTEMPLATEEX) pDlgTemplate)->wSignature == 0xFFFF) {
  861. dwExStyle = ((LPDLGTEMPLATEEX) pDlgTemplate)->dwExStyle;
  862. } else {
  863. dwExStyle = pDlgTemplate->dwExtendedStyle;
  864. }
  865. }
  866. if (dwExStyle & RTL_MIRRORED_WINDOW) {
  867. dwAppType = MIRRORED_APP;
  868. } else if (dwExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING)) {
  869. dwAppType = BIDI_APP;
  870. }
  871. return dwAppType;
  872. }
  873. LANGID GetDialogLanguage(HWND hwndOwner, HANDLE hDlgTemplate)
  874. {
  875. LANGID LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  876. DWORD dwType;
  877. if (GET_BIDI_LOCALIZED_SYSTEM_LANGID(&LangID)) {
  878. if (hDlgTemplate == NULL) {
  879. dwType = GetAppType(hwndOwner);
  880. } else {
  881. dwType = GetTemplateType(hDlgTemplate);
  882. }
  883. switch (dwType) {
  884. case ENGLISH_APP :
  885. LangID = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  886. break;
  887. case MIRRORED_APP:
  888. LangID = MAKELANGID(PRIMARYLANGID(LangID), SUBLANG_DEFAULT);
  889. break;
  890. case BIDI_APP :
  891. LangID = MAKELANGID(PRIMARYLANGID(LangID), SUBLANG_SYS_DEFAULT);
  892. break;
  893. }
  894. }
  895. return LangID;
  896. }
  897. HRESULT StringCopyOverlap(WCHAR *szDest, WCHAR *szSource)
  898. {
  899. size_t cchSource = lstrlen(szSource) + 1;
  900. MoveMemory(szDest, szSource, cchSource * sizeof(WCHAR));
  901. return S_OK;
  902. }
  903. HRESULT StringCchCopyOverlap(WCHAR *szDest, size_t cchDest, WCHAR *szSource)
  904. {
  905. HRESULT hr;
  906. size_t cchSource = lstrlen(szSource) + 1;
  907. if (cchSource <= cchDest)
  908. {
  909. // There is enough room.
  910. MoveMemory(szDest, szSource, cchSource * sizeof(WCHAR));
  911. hr = S_OK;
  912. }
  913. else
  914. {
  915. hr = E_FAIL;
  916. }
  917. return hr;
  918. }