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.

2011 lines
78 KiB

  1. /*
  2. * INSOBJ.CPP
  3. *
  4. * Implements the OleUIInsertObject function which invokes the complete
  5. * Insert Object dialog. Makes use of the OleChangeIcon function in
  6. * ICON.CPP.
  7. *
  8. * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9. */
  10. #include "precomp.h"
  11. #include "common.h"
  12. #include <commdlg.h>
  13. #include <memory.h>
  14. #include <dos.h>
  15. #include <stdlib.h>
  16. #include <reghelp.hxx>
  17. #include "utility.h"
  18. #include "resimage.h"
  19. #include "iconbox.h"
  20. #include "strcache.h"
  21. OLEDBGDATA
  22. #if USE_STRING_CACHE==1
  23. extern CStringCache gInsObjStringCache; //defined in strcache.cpp
  24. DWORD g_dwOldListType = 0;
  25. #endif
  26. // Internally used structure
  27. typedef struct tagINSERTOBJECT
  28. {
  29. LPOLEUIINSERTOBJECT lpOIO; // Original structure passed.
  30. UINT nIDD; // IDD of dialog (used for help info)
  31. /*
  32. * What we store extra in this structure besides the original caller's
  33. * pointer are those fields that we need to modify during the life of
  34. * the dialog but that we don't want to change in the original structure
  35. * until the user presses OK.
  36. */
  37. DWORD dwFlags;
  38. CLSID clsid;
  39. TCHAR szFile[MAX_PATH];
  40. BOOL fFileSelected; // Enables Display As Icon for links
  41. BOOL fAsIconNew;
  42. BOOL fAsIconFile;
  43. BOOL fFileDirty;
  44. BOOL fFileValid;
  45. UINT nErrCode;
  46. HGLOBAL hMetaPictFile;
  47. UINT nBrowseHelpID; // Help ID callback for Browse dlg
  48. BOOL bObjectListFilled;
  49. BOOL bControlListFilled;
  50. BOOL bControlListActive;
  51. } INSERTOBJECT, *PINSERTOBJECT, FAR *LPINSERTOBJECT;
  52. // Internal function prototypes
  53. // INSOBJ.CPP
  54. void EnableChangeIconButton(HWND hDlg, BOOL fEnable);
  55. INT_PTR CALLBACK InsertObjectDialogProc(HWND, UINT, WPARAM, LPARAM);
  56. BOOL FInsertObjectInit(HWND, WPARAM, LPARAM);
  57. UINT UFillClassList(HWND, UINT, LPCLSID, BOOL, BOOL);
  58. LRESULT URefillClassList(HWND, LPINSERTOBJECT);
  59. BOOL FToggleObjectSource(HWND, LPINSERTOBJECT, DWORD);
  60. void UpdateClassType(HWND, LPINSERTOBJECT, BOOL);
  61. void SetInsertObjectResults(HWND, LPINSERTOBJECT);
  62. BOOL FValidateInsertFile(HWND, BOOL, UINT FAR*);
  63. void InsertObjectCleanup(HWND);
  64. static void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList);
  65. BOOL CALLBACK HookDlgProc(HWND, UINT, WPARAM, LPARAM);
  66. #define IS_FILENAME_DELIM(c) ( (c) == '\\' || (c) == '/' || (c) == ':')
  67. BOOL CALLBACK HookDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  68. {
  69. #ifdef CHICO
  70. switch (uMsg)
  71. {
  72. case WM_INITDIALOG:
  73. TCHAR szTemp[MAX_PATH];
  74. LoadString(_g_hOleStdResInst, IDS_INSERT , szTemp, MAX_PATH);
  75. CommDlg_OpenSave_SetControlText(GetParent(hDlg), IDOK, szTemp);
  76. return(TRUE);
  77. default:
  78. break;
  79. }
  80. #endif
  81. return(FALSE);
  82. }
  83. /*
  84. * OleUIInsertObject
  85. *
  86. * Purpose:
  87. * Invokes the standard OLE Insert Object dialog box allowing the
  88. * user to select an object source and classname as well as the option
  89. * to display the object as itself or as an icon.
  90. *
  91. * Parameters:
  92. * lpIO LPOLEUIINSERTOBJECT pointing to the in-out structure
  93. * for this dialog.
  94. *
  95. * Return Value:
  96. * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise
  97. * an error value.
  98. */
  99. STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT lpIO)
  100. {
  101. HGLOBAL hMemDlg = NULL;
  102. UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpIO, sizeof(OLEUIINSERTOBJECT),
  103. &hMemDlg);
  104. if (OLEUI_SUCCESS != uRet)
  105. return uRet;
  106. //Now we can do Insert Object specific validation.
  107. if (NULL != lpIO->lpszFile &&
  108. (lpIO->cchFile <= 0 || lpIO->cchFile > MAX_PATH))
  109. {
  110. uRet = OLEUI_IOERR_CCHFILEINVALID;
  111. }
  112. // NULL is NOT valid for lpszFile
  113. if (lpIO->lpszFile == NULL)
  114. {
  115. uRet = OLEUI_IOERR_LPSZFILEINVALID;
  116. }
  117. else
  118. {
  119. if (IsBadWritePtr(lpIO->lpszFile, lpIO->cchFile*sizeof(TCHAR)))
  120. uRet = OLEUI_IOERR_LPSZFILEINVALID;
  121. }
  122. if (0 != lpIO->cClsidExclude &&
  123. IsBadReadPtr(lpIO->lpClsidExclude, lpIO->cClsidExclude * sizeof(CLSID)))
  124. {
  125. uRet = OLEUI_IOERR_LPCLSIDEXCLUDEINVALID;
  126. }
  127. //If we have flags to create any object, validate necessary data.
  128. if (lpIO->dwFlags & (IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT | IOF_CREATELINKOBJECT))
  129. {
  130. if (NULL != lpIO->lpFormatEtc
  131. && IsBadReadPtr(lpIO->lpFormatEtc, sizeof(FORMATETC)))
  132. uRet = OLEUI_IOERR_LPFORMATETCINVALID;
  133. if (NULL != lpIO->ppvObj && IsBadWritePtr(lpIO->ppvObj, sizeof(LPVOID)))
  134. uRet = OLEUI_IOERR_PPVOBJINVALID;
  135. if (NULL != lpIO->lpIOleClientSite
  136. && IsBadReadPtr(*(VOID**)&lpIO->lpIOleClientSite, sizeof(DWORD)))
  137. uRet = OLEUI_IOERR_LPIOLECLIENTSITEINVALID;
  138. if (NULL != lpIO->lpIStorage
  139. && IsBadReadPtr(*(VOID**)&lpIO->lpIStorage, sizeof(DWORD)))
  140. uRet = OLEUI_IOERR_LPISTORAGEINVALID;
  141. }
  142. if (OLEUI_ERR_STANDARDMIN <= uRet)
  143. {
  144. return uRet;
  145. }
  146. #if USE_STRING_CACHE==1
  147. // Inform the string cache about a fresh InsertObject invocation.
  148. gInsObjStringCache.NewCall(lpIO->dwFlags, lpIO->cClsidExclude);
  149. #endif
  150. //Now that we've validated everything, we can invoke the dialog.
  151. uRet = UStandardInvocation(InsertObjectDialogProc, (LPOLEUISTANDARD)lpIO,
  152. hMemDlg, MAKEINTRESOURCE(IDD_INSERTOBJECT));
  153. //Stop here if we cancelled or had an error.
  154. if (OLEUI_SUCCESS !=uRet && OLEUI_OK!=uRet)
  155. return uRet;
  156. /*
  157. * If any of the flags specify that we're to create objects on return
  158. * from this dialog, then do so. If we encounter an error in this
  159. * processing, we return OLEUI_IOERR_SCODEHASERROR. Since the
  160. * three select flags are mutually exclusive, we don't have to
  161. * if...else here, just if each case (keeps things cleaner that way).
  162. */
  163. lpIO->sc = S_OK;
  164. // Check if Create New was selected and we have IOF_CREATENEWOBJECT
  165. if ((lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL)) &&
  166. (lpIO->dwFlags & IOF_CREATENEWOBJECT))
  167. {
  168. HRESULT hrErr = OleCreate(lpIO->clsid, lpIO->iid, lpIO->oleRender,
  169. lpIO->lpFormatEtc, lpIO->lpIOleClientSite, lpIO->lpIStorage,
  170. lpIO->ppvObj);
  171. lpIO->sc = GetScode(hrErr);
  172. }
  173. // Try Create From File
  174. if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE))
  175. {
  176. if (!(lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATEFILEOBJECT))
  177. {
  178. HRESULT hrErr=OleCreateFromFile(CLSID_NULL, lpIO->lpszFile, lpIO->iid,
  179. lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite,
  180. lpIO->lpIStorage, lpIO->ppvObj);
  181. lpIO->sc = GetScode(hrErr);
  182. }
  183. if ((lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATELINKOBJECT))
  184. {
  185. HRESULT hrErr=OleCreateLinkToFile(lpIO->lpszFile, lpIO->iid,
  186. lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite,
  187. lpIO->lpIStorage, lpIO->ppvObj);
  188. lpIO->sc = GetScode(hrErr);
  189. }
  190. }
  191. //If we tried but failed a create option, then return the appropriate error
  192. if (S_OK != lpIO->sc)
  193. uRet = OLEUI_IOERR_SCODEHASERROR;
  194. return uRet;
  195. }
  196. /*
  197. * InsertObjectDialogProc
  198. *
  199. * Purpose:
  200. * Implements the OLE Insert Object dialog as invoked through the
  201. * OleUIInsertObject function.
  202. */
  203. INT_PTR CALLBACK InsertObjectDialogProc(HWND hDlg, UINT iMsg,
  204. WPARAM wParam, LPARAM lParam)
  205. {
  206. // Declare Win16/Win32 compatible WM_COMMAND parameters.
  207. COMMANDPARAMS(wID, wCode, hWndMsg);
  208. // This will fail under WM_INITDIALOG, where we allocate it.
  209. UINT uRet = 0;
  210. LPINSERTOBJECT lpIO = (LPINSERTOBJECT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
  211. // If the hook processed the message, we're done.
  212. if (0 != uRet)
  213. return (BOOL)uRet;
  214. // Process help message from Change Icon
  215. if (iMsg == uMsgHelp)
  216. {
  217. if (lpIO && (lpIO->lpOIO))
  218. PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, wParam, lParam);
  219. return FALSE;
  220. }
  221. // Process the temination message
  222. if (iMsg == uMsgEndDialog)
  223. {
  224. EndDialog(hDlg, wParam);
  225. return TRUE;
  226. }
  227. // The following messages do not require lpio to be non-null.
  228. switch (iMsg)
  229. {
  230. case WM_INITDIALOG:
  231. return FInsertObjectInit(hDlg, wParam, lParam);
  232. }
  233. // The following messages DO require lpIO to be non-null, so don't
  234. // continue processing if lpIO is NULL.
  235. if (NULL == lpIO)
  236. return FALSE;
  237. switch (iMsg)
  238. {
  239. case WM_DESTROY:
  240. InsertObjectCleanup(hDlg);
  241. StandardCleanup(lpIO, hDlg);
  242. break;
  243. case WM_COMMAND:
  244. switch (wID)
  245. {
  246. case IDC_IO_CREATENEW:
  247. if (1 == IsDlgButtonChecked(hDlg, IDC_IO_CREATENEW))
  248. {
  249. FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATENEW);
  250. SetFocus(GetDlgItem(hDlg, IDC_IO_CREATENEW));
  251. }
  252. break;
  253. case IDC_IO_CREATEFROMFILE:
  254. if (1 == IsDlgButtonChecked(hDlg, IDC_IO_CREATEFROMFILE))
  255. {
  256. FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATEFROMFILE);
  257. SetFocus(GetDlgItem(hDlg, IDC_IO_CREATEFROMFILE));
  258. }
  259. break;
  260. case IDC_IO_INSERTCONTROL:
  261. if (1 == IsDlgButtonChecked(hDlg, IDC_IO_INSERTCONTROL))
  262. {
  263. FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATECONTROL);
  264. SetFocus(GetDlgItem(hDlg, IDC_IO_INSERTCONTROL));
  265. }
  266. break;
  267. case IDC_IO_LINKFILE:
  268. {
  269. BOOL fCheck=IsDlgButtonChecked(hDlg, wID);
  270. if (fCheck)
  271. lpIO->dwFlags |=IOF_CHECKLINK;
  272. else
  273. lpIO->dwFlags &=~IOF_CHECKLINK;
  274. // Results change here, so be sure to update it.
  275. SetInsertObjectResults(hDlg, lpIO);
  276. UpdateClassIcon(hDlg, lpIO, NULL);
  277. }
  278. break;
  279. case IDC_IO_OBJECTTYPELIST:
  280. switch (wCode)
  281. {
  282. case LBN_SELCHANGE:
  283. UpdateClassIcon(hDlg, lpIO, hWndMsg);
  284. SetInsertObjectResults(hDlg, lpIO);
  285. break;
  286. case LBN_DBLCLK:
  287. SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
  288. break;
  289. }
  290. break;
  291. case IDC_IO_FILEDISPLAY:
  292. // If there are characters, enable OK and Display As Icon
  293. if (EN_CHANGE == wCode)
  294. {
  295. lpIO->fFileDirty = TRUE;
  296. lpIO->fFileValid = FALSE;
  297. lpIO->fFileSelected = (0L != SendMessage(hWndMsg, EM_LINELENGTH, 0, 0L));
  298. StandardEnableDlgItem(hDlg, IDC_IO_LINKFILE, lpIO->fFileSelected);
  299. StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, lpIO->fFileSelected);
  300. EnableChangeIconButton(hDlg, lpIO->fFileSelected);
  301. StandardEnableDlgItem(hDlg, IDOK, lpIO->fFileSelected);
  302. }
  303. if (EN_KILLFOCUS == wCode && NULL != lpIO)
  304. {
  305. if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
  306. {
  307. lpIO->fFileDirty = FALSE;
  308. lpIO->fFileValid = TRUE;
  309. UpdateClassIcon(hDlg, lpIO, NULL);
  310. UpdateClassType(hDlg, lpIO, TRUE);
  311. }
  312. else
  313. {
  314. lpIO->fFileDirty = FALSE;
  315. lpIO->fFileValid = FALSE;
  316. UpdateClassType(hDlg, lpIO, FALSE);
  317. }
  318. }
  319. break;
  320. case IDC_IO_DISPLAYASICON:
  321. {
  322. BOOL fCheck = IsDlgButtonChecked(hDlg, wID);
  323. if (fCheck)
  324. lpIO->dwFlags |=IOF_CHECKDISPLAYASICON;
  325. else
  326. lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
  327. // Update the internal flag based on this checking
  328. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  329. lpIO->fAsIconNew = fCheck;
  330. else
  331. lpIO->fAsIconFile = fCheck;
  332. // Re-read the class icon on Display checked
  333. if (fCheck)
  334. {
  335. if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  336. {
  337. if (FValidateInsertFile(hDlg, TRUE,&lpIO->nErrCode))
  338. {
  339. lpIO->fFileDirty = FALSE;
  340. lpIO->fFileValid = TRUE;
  341. UpdateClassIcon(hDlg, lpIO,
  342. GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
  343. UpdateClassType(hDlg, lpIO, TRUE);
  344. }
  345. else
  346. {
  347. lpIO->fAsIconFile= FALSE;
  348. lpIO->fFileDirty = FALSE;
  349. lpIO->fFileValid = FALSE;
  350. SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY,
  351. IBXM_IMAGESET, 0, 0L);
  352. UpdateClassType(hDlg, lpIO, FALSE);
  353. lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
  354. CheckDlgButton(hDlg, IDC_IO_DISPLAYASICON, 0);
  355. HWND hWndEC = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
  356. SetFocus(hWndEC);
  357. SendMessage(hWndEC, EM_SETSEL, 0, -1);
  358. return TRUE;
  359. }
  360. }
  361. else
  362. UpdateClassIcon(hDlg, lpIO,
  363. GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
  364. }
  365. // Results change here, so be sure to update it.
  366. SetInsertObjectResults(hDlg, lpIO);
  367. /*
  368. * Show or hide controls as appropriate. Do the icon
  369. * display last because it will take some time to repaint.
  370. * If we do it first then the dialog looks too sluggish.
  371. */
  372. UINT i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE;
  373. StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, i);
  374. StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, i);
  375. EnableChangeIconButton(hDlg, fCheck);
  376. }
  377. break;
  378. case IDC_IO_CHANGEICON:
  379. {
  380. // if we're in SELECTCREATEFROMFILE mode, then we need to Validate
  381. // the contents of the edit control first.
  382. if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  383. {
  384. if (lpIO->fFileDirty &&
  385. !FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
  386. {
  387. HWND hWndEC;
  388. lpIO->fFileValid = FALSE;
  389. hWndEC = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
  390. SetFocus(hWndEC);
  391. SendMessage(hWndEC, EM_SETSEL, 0, -1);
  392. return TRUE;
  393. }
  394. else
  395. {
  396. lpIO->fFileDirty = FALSE;
  397. }
  398. }
  399. // Initialize the structure for the hook.
  400. OLEUICHANGEICON ci; memset(&ci, 0, sizeof(ci));
  401. ci.cbStruct = sizeof(ci);
  402. ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
  403. IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  404. ci.hWndOwner= hDlg;
  405. ci.dwFlags = CIF_SELECTCURRENT;
  406. if (lpIO->dwFlags & IOF_SHOWHELP)
  407. ci.dwFlags |= CIF_SHOWHELP;
  408. HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
  409. int iCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  410. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  411. {
  412. LPTSTR pszString = (LPTSTR)OleStdMalloc(
  413. OLEUI_CCHKEYMAX_SIZE + OLEUI_CCHCLSIDSTRING_SIZE);
  414. SendMessage(hList, LB_GETTEXT, iCurSel, (LPARAM)pszString);
  415. LPTSTR pszCLSID = PointerToNthField(pszString, 2, '\t');
  416. CLSIDFromString(pszCLSID, &ci.clsid);
  417. OleStdFree((LPVOID)pszString);
  418. }
  419. else // IOF_SELECTCREATEFROMFILE
  420. {
  421. TCHAR szFileName[MAX_PATH];
  422. GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFileName, MAX_PATH);
  423. if (S_OK != GetClassFile(szFileName, &ci.clsid))
  424. {
  425. int istrlen = lstrlen(szFileName);
  426. LPTSTR lpszExtension = szFileName + istrlen -1;
  427. while (lpszExtension > szFileName &&
  428. *lpszExtension != '.')
  429. {
  430. lpszExtension = CharPrev(szFileName, lpszExtension);
  431. }
  432. GetAssociatedExecutable(lpszExtension, ci.szIconExe, sizeof(ci.szIconExe)/sizeof(ci.szIconExe[0]));
  433. ci.cchIconExe = lstrlen(ci.szIconExe);
  434. ci.dwFlags |= CIF_USEICONEXE;
  435. }
  436. }
  437. // Let the hook in to customize Change Icon if desired.
  438. uRet = UStandardHook(lpIO, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci);
  439. if (0 == uRet)
  440. uRet = (UINT)(OLEUI_OK == OleUIChangeIcon(&ci));
  441. // Update the display and itemdata if necessary.
  442. if (0 != uRet)
  443. {
  444. /*
  445. * OleUIChangeIcon will have already freed our
  446. * current hMetaPict that we passed in when OK is
  447. * pressed in that dialog. So we use 0L as lParam
  448. * here so the IconBox doesn't try to free the
  449. * metafilepict again.
  450. */
  451. SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY,
  452. IBXM_IMAGESET, 0, (LPARAM)ci.hMetaPict);
  453. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  454. SendMessage(hList, LB_SETITEMDATA, iCurSel, (LPARAM)ci.hMetaPict);
  455. }
  456. }
  457. break;
  458. case IDC_IO_FILE:
  459. {
  460. /*
  461. * To allow the hook to customize the browse dialog, we
  462. * send OLEUI_MSG_BROWSE. If the hook returns FALSE
  463. * we use the default, otherwise we trust that it retrieved
  464. * a filename for us. This mechanism prevents hooks from
  465. * trapping IDC_IO_BROWSE to customize the dialog and from
  466. * trying to figure out what we do after we have the name.
  467. */
  468. TCHAR szTemp[MAX_PATH];
  469. int nChars = GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szTemp, MAX_PATH);
  470. TCHAR szInitialDir[MAX_PATH];
  471. BOOL fUseInitialDir = FALSE;
  472. if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
  473. {
  474. StandardGetFileTitle(szTemp, lpIO->szFile, MAX_PATH);
  475. int istrlen = lstrlen(lpIO->szFile);
  476. lstrcpyn(szInitialDir, szTemp, nChars - istrlen);
  477. fUseInitialDir = TRUE;
  478. }
  479. else // file name isn't valid...lop off end of szTemp to get a
  480. // valid directory
  481. {
  482. TCHAR szBuffer[MAX_PATH];
  483. lstrcpyn(szBuffer, szTemp, sizeof(szBuffer)/sizeof(TCHAR));
  484. if ('\\' == szBuffer[nChars-1])
  485. szBuffer[nChars-1] = '\0';
  486. DWORD Attribs = GetFileAttributes(szBuffer);
  487. if (Attribs != 0xffffffff &&
  488. (Attribs & FILE_ATTRIBUTE_DIRECTORY) )
  489. {
  490. lstrcpy(szInitialDir, szBuffer);
  491. fUseInitialDir = TRUE;
  492. }
  493. *lpIO->szFile = '\0';
  494. }
  495. uRet = UStandardHook(lpIO, hDlg, uMsgBrowse,
  496. MAX_PATH, (LPARAM)(LPSTR)lpIO->szFile);
  497. if (0 == uRet)
  498. {
  499. DWORD dwOfnFlags = OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
  500. if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP)
  501. dwOfnFlags |= OFN_SHOWHELP;
  502. uRet = (UINT)Browse(hDlg, lpIO->szFile,
  503. fUseInitialDir ? szInitialDir : NULL, MAX_PATH,
  504. IDS_FILTERS, dwOfnFlags, ID_BROWSE_INSERTFILE, (LPOFNHOOKPROC)HookDlgProc);
  505. }
  506. // Only update if the file changed.
  507. if (0 != uRet && 0 != lstrcmpi(szTemp, lpIO->szFile))
  508. {
  509. SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, lpIO->szFile);
  510. lpIO->fFileSelected=TRUE;
  511. if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
  512. {
  513. lpIO->fFileDirty = FALSE;
  514. lpIO->fFileValid = TRUE;
  515. UpdateClassIcon(hDlg, lpIO, NULL);
  516. UpdateClassType(hDlg, lpIO, TRUE);
  517. // auto set OK to be default button if valid file
  518. SendMessage(hDlg, DM_SETDEFID,
  519. (WPARAM)GetDlgItem(hDlg, IDOK), 0L);
  520. SetFocus(GetDlgItem(hDlg, IDOK));
  521. }
  522. else // filename is invalid - set focus back to ec
  523. {
  524. HWND hWnd;
  525. lpIO->fFileDirty = FALSE;
  526. lpIO->fFileValid = FALSE;
  527. hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
  528. SetFocus(hWnd);
  529. SendMessage(hWnd, EM_SETSEL, 0, -1);
  530. }
  531. // Once we have a file, Display As Icon is always enabled
  532. StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, TRUE);
  533. // As well as OK
  534. StandardEnableDlgItem(hDlg, IDOK, TRUE);
  535. }
  536. }
  537. break;
  538. case IDC_IO_ADDCONTROL:
  539. {
  540. TCHAR szFileName[MAX_PATH];
  541. szFileName[0] = 0;
  542. // allow hook to customize
  543. uRet = UStandardHook(lpIO, hDlg, uMsgAddControl,
  544. MAX_PATH, (LPARAM)szFileName);
  545. if (0 == uRet)
  546. {
  547. DWORD dwOfnFlags = OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
  548. if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP)
  549. dwOfnFlags |= OFN_SHOWHELP;
  550. uRet = (UINT)Browse(hDlg, szFileName, NULL, MAX_PATH,
  551. IDS_OCX_FILTERS, dwOfnFlags, ID_BROWSE_ADDCONTROL , (LPOFNHOOKPROC)HookDlgProc);
  552. }
  553. if (0 != uRet)
  554. {
  555. // try to register the control DLL
  556. HINSTANCE hInst = LoadLibrary(szFileName);
  557. if (hInst == NULL)
  558. {
  559. PopupMessage(hDlg, IDS_ADDCONTROL, IDS_CANNOTLOADOCX,
  560. MB_OK | MB_ICONEXCLAMATION);
  561. break;
  562. }
  563. HRESULT (FAR STDAPICALLTYPE* lpfn)(void);
  564. (FARPROC&)lpfn = GetProcAddress(hInst, "DllRegisterServer");
  565. if (lpfn == NULL)
  566. {
  567. PopupMessage(hDlg, IDS_ADDCONTROL, IDS_NODLLREGISTERSERVER,
  568. MB_OK | MB_ICONEXCLAMATION);
  569. FreeLibrary(hInst);
  570. break;
  571. }
  572. if (FAILED((*lpfn)()))
  573. {
  574. PopupMessage(hDlg, IDS_ADDCONTROL, IDS_DLLREGISTERFAILED,
  575. MB_OK | MB_ICONEXCLAMATION);
  576. FreeLibrary(hInst);
  577. break;
  578. }
  579. // cleanup the DLL from memory
  580. FreeLibrary(hInst);
  581. // registered successfully -- refill the list box
  582. lpIO->bControlListFilled = FALSE;
  583. lpIO->bObjectListFilled = FALSE;
  584. URefillClassList(hDlg, lpIO);
  585. }
  586. }
  587. break;
  588. case IDOK:
  589. {
  590. if ((HWND)lParam != GetFocus())
  591. SetFocus((HWND)lParam);
  592. // If the file name is clean (already validated), or
  593. // if Create New is selected, then we can skip this part.
  594. if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) &&
  595. lpIO->fFileDirty)
  596. {
  597. if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
  598. {
  599. lpIO->fFileDirty = FALSE;
  600. lpIO->fFileValid = TRUE;
  601. UpdateClassIcon(hDlg, lpIO, NULL);
  602. UpdateClassType(hDlg, lpIO, TRUE);
  603. }
  604. else // filename is invalid - set focus back to ec
  605. {
  606. HWND hWnd;
  607. lpIO->fFileDirty = FALSE;
  608. lpIO->fFileValid = FALSE;
  609. hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
  610. SetFocus(hWnd);
  611. SendMessage(hWnd, EM_SETSEL, 0, -1);
  612. UpdateClassType(hDlg, lpIO, FALSE);
  613. }
  614. return TRUE; // eat this message
  615. }
  616. else if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) &&
  617. !lpIO->fFileValid)
  618. {
  619. // filename is invalid - set focus back to ec
  620. HWND hWnd;
  621. TCHAR szFile[MAX_PATH];
  622. if (0 != GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY,
  623. szFile, MAX_PATH))
  624. {
  625. OpenFileError(hDlg, lpIO->nErrCode, szFile);
  626. }
  627. lpIO->fFileDirty = FALSE;
  628. lpIO->fFileValid = FALSE;
  629. hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
  630. SetFocus(hWnd);
  631. SendMessage(hWnd, EM_SETSEL, 0, -1);
  632. UpdateClassType(hDlg, lpIO, FALSE);
  633. return TRUE; // eat this message
  634. }
  635. // Copy the necessary information back to the original struct
  636. LPOLEUIINSERTOBJECT lpOIO = lpIO->lpOIO;
  637. lpOIO->dwFlags = lpIO->dwFlags;
  638. if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL))
  639. {
  640. HWND hListBox = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
  641. UINT iCurSel = (UINT)SendMessage(hListBox, LB_GETCURSEL, 0, 0);
  642. if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
  643. {
  644. lpOIO->hMetaPict=(HGLOBAL)SendMessage(hListBox,
  645. LB_GETITEMDATA, iCurSel, 0L);
  646. /*
  647. * Set the item data to 0 here so that the cleanup
  648. * code doesn't delete the metafile.
  649. */
  650. SendMessage(hListBox, LB_SETITEMDATA, iCurSel, 0L);
  651. }
  652. else
  653. lpOIO->hMetaPict = (HGLOBAL)NULL;
  654. TCHAR szBuffer[OLEUI_CCHKEYMAX+OLEUI_CCHCLSIDSTRING];
  655. SendMessage(hListBox, LB_GETTEXT, iCurSel, (LPARAM)szBuffer);
  656. LPTSTR lpszCLSID = PointerToNthField(szBuffer, 2, '\t');
  657. CLSIDFromString(lpszCLSID, &lpOIO->clsid);
  658. }
  659. else // IOF_SELECTCREATEFROMFILE
  660. {
  661. if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
  662. {
  663. // get metafile here
  664. lpOIO->hMetaPict = (HGLOBAL)SendDlgItemMessage(
  665. hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  666. }
  667. else
  668. lpOIO->hMetaPict = (HGLOBAL)NULL;
  669. }
  670. GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY,
  671. lpIO->szFile, lpOIO->cchFile);
  672. lstrcpyn(lpOIO->lpszFile, lpIO->szFile, lpOIO->cchFile);
  673. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  674. }
  675. break;
  676. case IDCANCEL:
  677. SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
  678. break;
  679. case IDC_OLEUIHELP:
  680. PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp,
  681. (WPARAM)hDlg, MAKELPARAM(IDD_INSERTOBJECT, 0));
  682. break;
  683. }
  684. break;
  685. default:
  686. if (iMsg == lpIO->nBrowseHelpID)
  687. {
  688. PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp,
  689. (WPARAM)hDlg, MAKELPARAM(IDD_INSERTFILEBROWSE, 0));
  690. }
  691. if (iMsg == uMsgBrowseOFN &&
  692. lpIO->lpOIO && lpIO->lpOIO->hWndOwner)
  693. {
  694. SendMessage(lpIO->lpOIO->hWndOwner, uMsgBrowseOFN, wParam, lParam);
  695. }
  696. break;
  697. }
  698. return FALSE;
  699. }
  700. //+---------------------------------------------------------------------------
  701. //
  702. // Function: CheckButton
  703. //
  704. // Synopsis: Handles checking the radio buttons
  705. //
  706. // Arguments: [hDlg] - dialog handle
  707. // [iID] - ID of the button to check
  708. //
  709. // Returns: nothing
  710. //
  711. // History: 1-19-95 stevebl Created
  712. //
  713. // Notes: Used in place of CheckRadioButtons to avoid a GP fault under
  714. // win32s that arises from IDC_IO_CREATENEW, IDC_IO_CREATEFROMFILE
  715. // and IDC_IO_INSERTCONTROL not being contiguous.
  716. //
  717. //----------------------------------------------------------------------------
  718. void CheckButton(HWND hDlg, int iID)
  719. {
  720. CheckDlgButton(hDlg, IDC_IO_CREATENEW, iID == IDC_IO_CREATENEW ? 1 : 0);
  721. CheckDlgButton(hDlg, IDC_IO_CREATEFROMFILE, iID == IDC_IO_CREATEFROMFILE ? 1 : 0);
  722. CheckDlgButton(hDlg, IDC_IO_INSERTCONTROL, iID == IDC_IO_INSERTCONTROL ? 1 : 0);
  723. }
  724. /*
  725. * FInsertObjectInit
  726. *
  727. * Purpose:
  728. * WM_INITIDIALOG handler for the Insert Object dialog box.
  729. *
  730. * Parameters:
  731. * hDlg HWND of the dialog
  732. * wParam WPARAM of the message
  733. * lParam LPARAM of the message
  734. *
  735. * Return Value:
  736. * BOOL Value to return for WM_INITDIALOG.
  737. */
  738. BOOL FInsertObjectInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
  739. {
  740. // Copy the structure at lParam into our instance memory.
  741. HFONT hFont;
  742. LPINSERTOBJECT lpIO = (LPINSERTOBJECT)LpvStandardInit(hDlg, sizeof(INSERTOBJECT), &hFont);
  743. // PvStandardInit send a termination to us already.
  744. if (NULL == lpIO)
  745. return FALSE;
  746. LPOLEUIINSERTOBJECT lpOIO = (LPOLEUIINSERTOBJECT)lParam;
  747. // Save the original pointer and copy necessary information.
  748. lpIO->lpOIO = lpOIO;
  749. lpIO->nIDD = IDD_INSERTOBJECT;
  750. lpIO->dwFlags = lpOIO->dwFlags;
  751. lpIO->clsid = lpOIO->clsid;
  752. if ((lpOIO->lpszFile) && ('\0' != *lpOIO->lpszFile))
  753. lstrcpyn(lpIO->szFile, lpOIO->lpszFile, MAX_PATH);
  754. else
  755. *(lpIO->szFile) = '\0';
  756. lpIO->hMetaPictFile = (HGLOBAL)NULL;
  757. // If we got a font, send it to the necessary controls.
  758. if (NULL != hFont)
  759. {
  760. SendDlgItemMessage(hDlg, IDC_IO_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
  761. SendDlgItemMessage(hDlg, IDC_IO_FILETYPE, WM_SETFONT, (WPARAM)hFont, 0L);
  762. }
  763. // Initilize the file name display to cwd if we don't have any name.
  764. if ('\0' == *(lpIO->szFile))
  765. {
  766. TCHAR szCurDir[MAX_PATH];
  767. int nLen;
  768. GetCurrentDirectory(MAX_PATH, szCurDir);
  769. nLen = lstrlen(szCurDir);
  770. if (nLen != 0 && szCurDir[nLen-1] != '\\')
  771. lstrcat(szCurDir, _T("\\"));
  772. SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szCurDir);
  773. lpIO->fFileDirty = TRUE; // cwd is not a valid filename
  774. }
  775. else
  776. {
  777. SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, lpIO->szFile);
  778. if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
  779. {
  780. lpIO->fFileDirty = FALSE;
  781. lpIO->fFileValid = TRUE;
  782. }
  783. else
  784. {
  785. lpIO->fFileDirty = TRUE;
  786. lpIO->fFileValid = FALSE;
  787. }
  788. }
  789. // Initialize radio button and related controls
  790. if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
  791. {
  792. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  793. lpIO->fAsIconNew = TRUE;
  794. else
  795. lpIO->fAsIconFile = TRUE;
  796. }
  797. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  798. CheckButton(hDlg, IDC_IO_CREATENEW);
  799. if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  800. CheckButton(hDlg, IDC_IO_CREATEFROMFILE);
  801. if (lpIO->dwFlags & IOF_SELECTCREATECONTROL)
  802. CheckButton(hDlg, IDC_IO_INSERTCONTROL);
  803. CheckDlgButton(hDlg, IDC_IO_LINKFILE, (BOOL)(0L != (lpIO->dwFlags & IOF_CHECKLINK)));
  804. lpIO->dwFlags &=
  805. ~(IOF_SELECTCREATENEW|IOF_SELECTCREATEFROMFILE|IOF_SELECTCREATECONTROL);
  806. FToggleObjectSource(hDlg, lpIO, lpOIO->dwFlags &
  807. (IOF_SELECTCREATENEW|IOF_SELECTCREATEFROMFILE|IOF_SELECTCREATECONTROL));
  808. // Show or hide the help button
  809. if (!(lpIO->dwFlags & IOF_SHOWHELP))
  810. StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE);
  811. // Show or hide the Change icon button
  812. if (lpIO->dwFlags & IOF_HIDECHANGEICON)
  813. DestroyWindow(GetDlgItem(hDlg, IDC_IO_CHANGEICON));
  814. // Hide Insert Control button if necessary
  815. if (!(lpIO->dwFlags & IOF_SHOWINSERTCONTROL))
  816. StandardShowDlgItem(hDlg, IDC_IO_INSERTCONTROL, SW_HIDE);
  817. // Initialize the result display
  818. UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
  819. SetInsertObjectResults(hDlg, lpIO);
  820. // Change the caption
  821. if (NULL!=lpOIO->lpszCaption)
  822. SetWindowText(hDlg, lpOIO->lpszCaption);
  823. // Hide all DisplayAsIcon related controls if it should be disabled
  824. if (lpIO->dwFlags & IOF_DISABLEDISPLAYASICON)
  825. {
  826. StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_HIDE);
  827. StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, SW_HIDE);
  828. StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, SW_HIDE);
  829. }
  830. lpIO->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING);
  831. // All Done: call the hook with lCustData
  832. UStandardHook(lpIO, hDlg, WM_INITDIALOG, wParam, lpOIO->lCustData);
  833. /*
  834. * We either set focus to the listbox or the edit control. In either
  835. * case we don't want Windows to do any SetFocus, so we return FALSE.
  836. */
  837. return FALSE;
  838. }
  839. /*
  840. * URefillClassList
  841. *
  842. * Purpose:
  843. * Fills the class list box with names as appropriate for the current
  844. * flags. This function is called when the user changes the flags
  845. * via the "exclusion" radio buttons.
  846. *
  847. * Note that this function removes any prior contents of the listbox.
  848. *
  849. * Parameters:
  850. * hDlg HWND to the dialog box.
  851. * lpIO pointer to LPINSERTOBJECT structure
  852. *
  853. * Return Value:
  854. * LRESULT Number of strings added to the listbox, -1 on failure.
  855. */
  856. LRESULT URefillClassList(HWND hDlg, LPINSERTOBJECT lpIO)
  857. {
  858. OleDbgAssert(lpIO->dwFlags & (IOF_SELECTCREATECONTROL|IOF_SELECTCREATENEW));
  859. // always the same dialog ID because they are swapped
  860. HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
  861. // determine if already filled
  862. BOOL bFilled;
  863. if (lpIO->dwFlags & IOF_SELECTCREATECONTROL)
  864. bFilled = lpIO->bControlListFilled;
  865. else
  866. bFilled = lpIO->bObjectListFilled;
  867. if (!bFilled)
  868. {
  869. // fill the list
  870. LPOLEUIINSERTOBJECT lpOIO = lpIO->lpOIO;
  871. UINT uResult = UFillClassList(hList, lpOIO->cClsidExclude, lpOIO->lpClsidExclude,
  872. (BOOL)(lpIO->dwFlags & IOF_VERIFYSERVERSEXIST),
  873. (lpIO->dwFlags & IOF_SELECTCREATECONTROL));
  874. // mark the list as filled
  875. if (lpIO->dwFlags & IOF_SELECTCREATECONTROL)
  876. lpIO->bControlListFilled = TRUE;
  877. else
  878. lpIO->bObjectListFilled = TRUE;
  879. }
  880. // return number of items now in the list
  881. return SendMessage(hList, LB_GETCOUNT, 0, 0);
  882. }
  883. /*
  884. * UFillClassList
  885. *
  886. * Purpose:
  887. * Enumerates available OLE object classes from the registration
  888. * database and fills a listbox with those names.
  889. *
  890. * Note that this function removes any prior contents of the listbox.
  891. *
  892. * Parameters:
  893. * hList HWND to the listbox to fill.
  894. * cIDEx UINT number of CLSIDs to exclude in lpIDEx
  895. * lpIDEx LPCLSID to CLSIDs to leave out of the listbox.
  896. * fVerify BOOL indicating if we are to validate existence of
  897. * servers before putting them in the list.
  898. *
  899. * Return Value:
  900. * UINT Number of strings added to the listbox, -1 on failure.
  901. */
  902. UINT UFillClassList(HWND hList, UINT cIDEx, LPCLSID lpIDEx, BOOL fVerify,
  903. BOOL fExcludeObjects)
  904. {
  905. OleDbgAssert(hList != NULL);
  906. // Set the tab width in the list to push all the tabs off the side.
  907. RECT rc;
  908. GetClientRect(hList, &rc);
  909. DWORD dw = GetDialogBaseUnits();
  910. rc.right =(8*rc.right)/LOWORD(dw); //Convert pixels to 2x dlg units.
  911. SendMessage(hList, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&rc.right);
  912. // Clean out the existing strings.
  913. SendMessage(hList, LB_RESETCONTENT, 0, 0L);
  914. UINT cStrings = 0;
  915. #if USE_STRING_CACHE==1
  916. if (gInsObjStringCache.OKToUse() && gInsObjStringCache.IsUptodate())
  917. {
  918. // IsUptodate returns false if the cache is not yet populated
  919. // or if any CLSID key changed in the registry since the last
  920. // time the cache was populated.
  921. LPCTSTR lpStr;
  922. // Reset enumerator in the cache.
  923. gInsObjStringCache.ResetEnumerator();
  924. while ( (lpStr = gInsObjStringCache.NextString()) != NULL)
  925. {
  926. SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)lpStr);
  927. cStrings++;
  928. }
  929. }
  930. else
  931. {
  932. // Setup the cache if it was successfully initialized and
  933. // there were no errors in a previous use.
  934. if (gInsObjStringCache.OKToUse())
  935. {
  936. // Clear the string counter and enumerator.
  937. // We will fill up the cache with strings in this round.
  938. gInsObjStringCache.FlushCache();
  939. }
  940. #endif
  941. LPTSTR pszExec = (LPTSTR)OleStdMalloc(OLEUI_CCHKEYMAX_SIZE*4);
  942. if (NULL == pszExec)
  943. return (UINT)-1;
  944. LPTSTR pszClass = pszExec+OLEUI_CCHKEYMAX;
  945. LPTSTR pszKey = pszClass+OLEUI_CCHKEYMAX;
  946. // Open up the root key.
  947. HKEY hKey;
  948. LONG lRet = OpenClassesRootKey(NULL, &hKey);
  949. if ((LONG)ERROR_SUCCESS!=lRet)
  950. {
  951. OleStdFree((LPVOID)pszExec);
  952. return (UINT)-1;
  953. }
  954. // We will now loop over all ProgIDs and add candidates that
  955. // pass various insertable tests to the ListBox one by one.
  956. while (TRUE)
  957. {
  958. // assume not yet (for handling of OLE1.0 compat case)
  959. BOOL bHaveCLSID = FALSE;
  960. LPTSTR pszID = pszKey+OLEUI_CCHKEYMAX;
  961. lRet = RegEnumKey(hKey, cStrings++, pszClass, OLEUI_CCHKEYMAX_SIZE);
  962. if ((LONG)ERROR_SUCCESS != lRet)
  963. break;
  964. if (!iswalpha(pszClass[0]))
  965. {
  966. // avoids looking into ".ext" type entries under HKCR
  967. continue;
  968. }
  969. // Cheat on lstrcat by using lstrcpy after this string, saving time
  970. UINT cch = lstrlen(pszClass);
  971. // Check for \NotInsertable. If this is found then this overrides
  972. // all other keys; this class will NOT be added to the InsertObject
  973. // list.
  974. lstrcpy(pszClass+cch, TEXT("\\NotInsertable"));
  975. HKEY hKeyTemp = NULL;
  976. lRet = RegOpenKey(hKey, pszClass, &hKeyTemp);
  977. if (hKeyTemp != NULL)
  978. RegCloseKey(hKeyTemp);
  979. if ((LONG)ERROR_SUCCESS == lRet)
  980. continue; // NotInsertable IS found--skip this class
  981. // check if ProgId says "Insertable"
  982. lstrcpy(pszClass+cch, TEXT("\\Insertable"));
  983. hKeyTemp = NULL;
  984. lRet = RegOpenKey(hKey, pszClass, &hKeyTemp);
  985. if (hKeyTemp != NULL)
  986. RegCloseKey(hKeyTemp);
  987. if (lRet == ERROR_SUCCESS || fExcludeObjects)
  988. {
  989. // ProgId says insertable (=> can't be OLE 1.0)
  990. // See if we are displaying Objects or Controls
  991. // Check for CLSID
  992. lstrcpy(pszClass+cch, TEXT("\\CLSID"));
  993. dw = OLEUI_CCHKEYMAX_SIZE;
  994. lRet = RegQueryValue(hKey, pszClass, pszID, (LONG*)&dw);
  995. if ((LONG)ERROR_SUCCESS != lRet)
  996. continue; // CLSID subkey not found
  997. bHaveCLSID = TRUE;
  998. // CLSID\ is 6, dw contains pszID length.
  999. cch = 6 + ((UINT)dw/sizeof(TCHAR)) - 1;
  1000. lstrcpy(pszExec, TEXT("CLSID\\"));
  1001. lstrcpy(pszExec+6, pszID);
  1002. // fExcludeObjects is TRUE for the Insert Control box.
  1003. // It's FALSE for the Insert Object box.
  1004. lstrcpy(pszExec+cch, TEXT("\\Control"));
  1005. hKeyTemp = NULL;
  1006. lRet = RegOpenKey(hKey, pszExec, &hKeyTemp);
  1007. if (hKeyTemp != NULL)
  1008. RegCloseKey(hKeyTemp);
  1009. if (!fExcludeObjects)
  1010. {
  1011. // We are listing Objects.
  1012. if (lRet == ERROR_SUCCESS)
  1013. {
  1014. // this is a control
  1015. continue;
  1016. }
  1017. }
  1018. else
  1019. {
  1020. // We are listing controls
  1021. if (lRet != ERROR_SUCCESS)
  1022. {
  1023. // This is an Object
  1024. continue;
  1025. }
  1026. // Some generous soul at some point of time in the past
  1027. // decided that for controls it is OK to have the
  1028. // Inertable key on the clsid too. So we have to perform
  1029. // that additional check before we decide if the control
  1030. // entry should be listed or not.
  1031. lstrcpy(pszExec+cch, TEXT("\\Insertable"));
  1032. hKeyTemp = NULL;
  1033. lRet = RegOpenKey(hKey, pszExec, &hKeyTemp);
  1034. if (hKeyTemp != NULL)
  1035. RegCloseKey(hKeyTemp);
  1036. if ((LONG)ERROR_SUCCESS != lRet)
  1037. continue;
  1038. }
  1039. // This is beginning to look like a probable list candidate
  1040. // Check \LocalServer32, LocalServer, and \InprocServer
  1041. // if we were requested to (IOF_VERIFYSERVERSEXIST)
  1042. if (fVerify)
  1043. {
  1044. // Try LocalServer32
  1045. lstrcpy(pszExec+cch, TEXT("\\LocalServer32"));
  1046. dw = OLEUI_CCHKEYMAX_SIZE;
  1047. lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
  1048. if ((LONG)ERROR_SUCCESS != lRet)
  1049. {
  1050. // Try LocalServer
  1051. lstrcpy(pszExec+cch, TEXT("\\LocalServer"));
  1052. dw = OLEUI_CCHKEYMAX_SIZE;
  1053. lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
  1054. if ((LONG)ERROR_SUCCESS != lRet)
  1055. {
  1056. // Try InprocServer32
  1057. lstrcpy(pszExec+cch, TEXT("\\InProcServer32"));
  1058. dw = OLEUI_CCHKEYMAX_SIZE;
  1059. lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
  1060. if ((LONG)ERROR_SUCCESS != lRet)
  1061. {
  1062. // Try InprocServer
  1063. lstrcpy(pszExec+cch, TEXT("\\InProcServer"));
  1064. dw = OLEUI_CCHKEYMAX_SIZE;
  1065. lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
  1066. if ((LONG)ERROR_SUCCESS != lRet)
  1067. continue;
  1068. }
  1069. }
  1070. }
  1071. if (!DoesFileExist(pszKey, OLEUI_CCHKEYMAX))
  1072. continue;
  1073. } //fVerify
  1074. // Get the readable name for the server.
  1075. // We'll needed it for the listbox.
  1076. *(pszExec+cch) = 0; //Remove \\*Server
  1077. dw = OLEUI_CCHKEYMAX_SIZE;
  1078. lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
  1079. if ((LONG)ERROR_SUCCESS!=lRet)
  1080. continue;
  1081. }
  1082. else
  1083. {
  1084. // We did not see an "Insertable" under ProgId, can
  1085. // this be an OLE 1.0 time server entry?
  1086. // Check for a \protocol\StdFileEditing\server entry.
  1087. lstrcpy(pszClass+cch, TEXT("\\protocol\\StdFileEditing\\server"));
  1088. DWORD dwTemp = OLEUI_CCHKEYMAX_SIZE;
  1089. lRet = RegQueryValue(hKey, pszClass, pszKey, (LONG*)&dwTemp);
  1090. if ((LONG)ERROR_SUCCESS == lRet)
  1091. {
  1092. // This is not a control
  1093. // skip it if excluding non-controls
  1094. if (fExcludeObjects)
  1095. continue;
  1096. // Check if the EXE actually exists.
  1097. // (By default we don't do this for speed.
  1098. // If an application wants to, it must provide
  1099. // IOF_VERIFYSERVERSEXIST flag in the request)
  1100. if (fVerify && !DoesFileExist(pszKey, OLEUI_CCHKEYMAX))
  1101. continue;
  1102. // get readable class name
  1103. dwTemp = OLEUI_CCHKEYMAX_SIZE;
  1104. *(pszClass+cch) = 0; // set back to rootkey
  1105. lRet=RegQueryValue(hKey, pszClass, pszKey, (LONG*)&dwTemp);
  1106. // attempt to get clsid directly from registry
  1107. lstrcpy(pszClass+cch, TEXT("\\CLSID"));
  1108. dwTemp = OLEUI_CCHKEYMAX_SIZE;
  1109. lRet = RegQueryValue(hKey, pszClass, pszID, (LONG*)&dwTemp);
  1110. if ((LONG)ERROR_SUCCESS == lRet)
  1111. bHaveCLSID = TRUE;
  1112. *(pszClass+cch) = 0; // set back to rootkey
  1113. }
  1114. else
  1115. {
  1116. // This is not OLE 1.0 either!
  1117. continue;
  1118. }
  1119. }
  1120. // At this point we have an insertable candidate.
  1121. // or OLE 1.0 time.
  1122. // get CLSID to add to listbox.
  1123. CLSID clsid;
  1124. if (!bHaveCLSID)
  1125. {
  1126. if (FAILED(CLSIDFromProgID(pszClass, &clsid)))
  1127. continue;
  1128. if (FAILED(StringFromCLSID(clsid, &pszID)))
  1129. continue;
  1130. }
  1131. else
  1132. {
  1133. if (FAILED(CLSIDFromString(pszID, &clsid)))
  1134. continue;
  1135. }
  1136. // ##### WARNING #####: using 'continue' after this point
  1137. // would leak memory so don't use it!
  1138. // check if this CLSID is in the exclusion list.
  1139. BOOL fExclude = FALSE;
  1140. for (UINT i=0; i < cIDEx; i++)
  1141. {
  1142. if (IsEqualCLSID(clsid, lpIDEx[i]))
  1143. {
  1144. fExclude=TRUE;
  1145. break;
  1146. }
  1147. }
  1148. // don't add objects without names
  1149. if (lstrlen(pszKey) > 0 && !fExclude)
  1150. {
  1151. // We got through all the conditions, add the string.
  1152. if (LB_ERR == SendMessage(hList, LB_FINDSTRING, 0, (LPARAM)pszKey))
  1153. {
  1154. pszKey[cch = lstrlen(pszKey)] = '\t';
  1155. lstrcpy(pszKey+cch+1, pszID);
  1156. SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)pszKey);
  1157. #if USE_STRING_CACHE==1
  1158. if (gInsObjStringCache.OKToUse())
  1159. {
  1160. if (!gInsObjStringCache.AddString(pszKey))
  1161. {
  1162. // Adding the string failed due to some reason
  1163. OleDbgAssert(!"Failure adding string");
  1164. // A failed Add() should mark the
  1165. // Cache not OK to use any more.
  1166. OleDbgAssert(!gInsObjStringCache.OKToUse())
  1167. }
  1168. }
  1169. #endif
  1170. }
  1171. }
  1172. if (!bHaveCLSID)
  1173. OleStdFree((LPVOID)pszID);
  1174. } // While (TRUE)
  1175. RegCloseKey(hKey);
  1176. OleStdFree((LPVOID)pszExec);
  1177. #if USE_STRING_CACHE
  1178. }
  1179. #endif
  1180. // Select the first item by default
  1181. SendMessage(hList, LB_SETCURSEL, 0, 0L);
  1182. return cStrings;
  1183. }
  1184. /*
  1185. * FToggleObjectSource
  1186. *
  1187. * Purpose:
  1188. * Handles enabling, disabling, showing, and flag manipulation when the
  1189. * user changes between Create New, Insert File, and Link File in the
  1190. * Insert Object dialog.
  1191. *
  1192. * Parameters:
  1193. * hDlg HWND of the dialog
  1194. * lpIO LPINSERTOBJECT pointing to the dialog structure
  1195. * dwOption DWORD flag indicating the option just selected:
  1196. * IOF_SELECTCREATENEW or IOF_SELECTCREATEFROMFILE
  1197. *
  1198. * Return Value:
  1199. * BOOL TRUE if the option was already selected, FALSE otherwise.
  1200. */
  1201. BOOL FToggleObjectSource(HWND hDlg, LPINSERTOBJECT lpIO, DWORD dwOption)
  1202. {
  1203. // Skip all of this if we're already selected.
  1204. if (lpIO->dwFlags & dwOption)
  1205. return TRUE;
  1206. #ifdef USE_STRING_CACHE
  1207. // if we're using string cache, we need to flush the cache if
  1208. // the list previously displayed was of different type
  1209. if(IOF_SELECTCREATECONTROL == dwOption)
  1210. {
  1211. if(g_dwOldListType == IOF_SELECTCREATENEW)
  1212. gInsObjStringCache.FlushCache();
  1213. g_dwOldListType = IOF_SELECTCREATECONTROL;
  1214. }
  1215. else if(IOF_SELECTCREATENEW == dwOption)
  1216. {
  1217. if(g_dwOldListType == IOF_SELECTCREATECONTROL)
  1218. gInsObjStringCache.FlushCache();
  1219. g_dwOldListType = IOF_SELECTCREATENEW;
  1220. }
  1221. #endif
  1222. // if we're switching from "from file" to "create new" and we've got
  1223. // an icon for "from file", then we need to save it so that we can
  1224. // show it if the user reselects "from file".
  1225. if ((IOF_SELECTCREATENEW == dwOption) &&
  1226. (lpIO->dwFlags & IOF_CHECKDISPLAYASICON))
  1227. {
  1228. lpIO->hMetaPictFile = (HGLOBAL)SendDlgItemMessage(hDlg,
  1229. IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  1230. }
  1231. /*
  1232. * 1. Change the Display As Icon checked state to reflect the
  1233. * selection for this option, stored in the fAsIcon* flags.
  1234. */
  1235. BOOL fTemp;
  1236. if (IOF_SELECTCREATENEW == dwOption)
  1237. fTemp = lpIO->fAsIconNew;
  1238. else if (IOF_SELECTCREATEFROMFILE == dwOption)
  1239. fTemp = lpIO->fAsIconFile;
  1240. else
  1241. fTemp = FALSE;
  1242. if (fTemp)
  1243. lpIO->dwFlags |= IOF_CHECKDISPLAYASICON;
  1244. else
  1245. lpIO->dwFlags &= ~IOF_CHECKDISPLAYASICON;
  1246. CheckDlgButton(hDlg, IDC_IO_DISPLAYASICON,
  1247. (BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)));
  1248. EnableChangeIconButton(hDlg, fTemp);
  1249. /*
  1250. * Display Icon: Enabled on Create New or on Create from File if
  1251. * there is a selected file.
  1252. */
  1253. if (IOF_SELECTCREATENEW == dwOption)
  1254. fTemp = TRUE;
  1255. else if (IOF_SELECTCREATEFROMFILE == dwOption)
  1256. fTemp = lpIO->fFileSelected;
  1257. else
  1258. fTemp = FALSE;
  1259. if (IOF_SELECTCREATECONTROL == dwOption)
  1260. StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_HIDE);
  1261. else if (!(lpIO->dwFlags & IOF_DISABLEDISPLAYASICON))
  1262. StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_SHOW);
  1263. StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, fTemp);
  1264. // OK and Link follow the same enabling as Display As Icon.
  1265. StandardEnableDlgItem(hDlg, IDOK,
  1266. fTemp || IOF_SELECTCREATECONTROL == dwOption);
  1267. StandardEnableDlgItem(hDlg, IDC_IO_LINKFILE, fTemp);
  1268. // Enable Browse... when Create from File is selected.
  1269. fTemp = (IOF_SELECTCREATEFROMFILE != dwOption);
  1270. StandardEnableDlgItem(hDlg, IDC_IO_FILE, !fTemp);
  1271. StandardEnableDlgItem(hDlg, IDC_IO_FILEDISPLAY, !fTemp);
  1272. // Switch Object Type & Control Type listboxes if necessary
  1273. HWND hWnd1 = NULL, hWnd2 = NULL;
  1274. if (lpIO->bControlListActive && IOF_SELECTCREATENEW == dwOption)
  1275. {
  1276. hWnd1 = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
  1277. hWnd2 = GetDlgItem(hDlg, IDC_IO_CONTROLTYPELIST);
  1278. SetWindowLong(hWnd1, GWL_ID, IDC_IO_CONTROLTYPELIST);
  1279. SetWindowLong(hWnd2, GWL_ID, IDC_IO_OBJECTTYPELIST);
  1280. lpIO->bControlListActive = FALSE;
  1281. }
  1282. else if (!lpIO->bControlListActive && IOF_SELECTCREATECONTROL == dwOption)
  1283. {
  1284. hWnd1 = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
  1285. hWnd2 = GetDlgItem(hDlg, IDC_IO_CONTROLTYPELIST);
  1286. SetWindowLong(hWnd1, GWL_ID, IDC_IO_CONTROLTYPELIST);
  1287. SetWindowLong(hWnd2, GWL_ID, IDC_IO_OBJECTTYPELIST);
  1288. lpIO->bControlListActive = TRUE;
  1289. }
  1290. // Clear out any existing selection flags and set the new one
  1291. DWORD dwTemp = IOF_SELECTCREATENEW | IOF_SELECTCREATEFROMFILE |
  1292. IOF_SELECTCREATECONTROL;
  1293. lpIO->dwFlags = (lpIO->dwFlags & ~dwTemp) | dwOption;
  1294. if (dwOption & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL))
  1295. {
  1296. // refill class list box if necessary
  1297. if ((lpIO->bControlListActive && !lpIO->bControlListFilled) ||
  1298. (!lpIO->bControlListActive && !lpIO->bObjectListFilled))
  1299. {
  1300. URefillClassList(hDlg, lpIO);
  1301. }
  1302. }
  1303. if (hWnd1 != NULL && hWnd2 != NULL)
  1304. {
  1305. ShowWindow(hWnd1, SW_HIDE);
  1306. ShowWindow(hWnd2, SW_SHOW);
  1307. }
  1308. /*
  1309. * Switch between Object Type listbox on Create New and
  1310. * file buttons on others.
  1311. */
  1312. UINT uTemp = (fTemp) ? SW_SHOWNORMAL : SW_HIDE;
  1313. StandardShowDlgItem(hDlg, IDC_IO_OBJECTTYPELIST, uTemp);
  1314. StandardShowDlgItem(hDlg, IDC_IO_OBJECTTYPETEXT, uTemp);
  1315. uTemp = (fTemp) ? SW_HIDE : SW_SHOWNORMAL;
  1316. StandardShowDlgItem(hDlg, IDC_IO_FILETEXT, uTemp);
  1317. StandardShowDlgItem(hDlg, IDC_IO_FILETYPE, uTemp);
  1318. StandardShowDlgItem(hDlg, IDC_IO_FILEDISPLAY, uTemp);
  1319. StandardShowDlgItem(hDlg, IDC_IO_FILE, uTemp);
  1320. // Link is always hidden if IOF_DISABLELINK is set.
  1321. if (IOF_DISABLELINK & lpIO->dwFlags)
  1322. uTemp = SW_HIDE;
  1323. StandardShowDlgItem(hDlg, IDC_IO_LINKFILE, uTemp); //last use of uTemp
  1324. // Remove add button when not in Insert control mode
  1325. uTemp = (IOF_SELECTCREATECONTROL == dwOption) ? SW_SHOW : SW_HIDE;
  1326. StandardShowDlgItem(hDlg, IDC_IO_ADDCONTROL, uTemp);
  1327. /*
  1328. * Show or hide controls as appropriate. Do the icon
  1329. * display last because it will take some time to repaint.
  1330. * If we do it first then the dialog looks too sluggish.
  1331. */
  1332. int i = (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) ? SW_SHOWNORMAL : SW_HIDE;
  1333. StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, i);
  1334. StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, i);
  1335. EnableChangeIconButton(hDlg, SW_SHOWNORMAL == i);
  1336. // Change result display
  1337. SetInsertObjectResults(hDlg, lpIO);
  1338. /*
  1339. * For Create New, twiddle the listbox to think we selected it
  1340. * so it updates the icon from the object type. set the focus
  1341. * to the list box.
  1342. *
  1343. * For Insert or Link file, set the focus to the filename button
  1344. * and update the icon if necessary.
  1345. */
  1346. if (fTemp)
  1347. {
  1348. UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
  1349. SetFocus(GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
  1350. }
  1351. else
  1352. {
  1353. if (lpIO->fAsIconFile && (NULL != lpIO->hMetaPictFile) )
  1354. {
  1355. SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET, 0,
  1356. (LPARAM)lpIO->hMetaPictFile);
  1357. lpIO->hMetaPictFile = 0;
  1358. }
  1359. else
  1360. {
  1361. UpdateClassIcon(hDlg, lpIO, NULL);
  1362. }
  1363. SetFocus(GetDlgItem(hDlg, IDC_IO_FILE));
  1364. }
  1365. return FALSE;
  1366. }
  1367. /*
  1368. * UpdateClassType
  1369. *
  1370. * Purpose:
  1371. * Updates static text control to reflect current file type. Assumes
  1372. * a valid filename.
  1373. *
  1374. * Parameters
  1375. * hDlg HWND of the dialog box.
  1376. * lpIO LPINSERTOBJECT pointing to the dialog structure
  1377. * fSet TRUE to set the text, FALSE to explicitly clear it
  1378. *
  1379. * Return Value:
  1380. * None
  1381. */
  1382. void UpdateClassType(HWND hDlg, LPINSERTOBJECT lpIO, BOOL fSet)
  1383. {
  1384. LPTSTR lpszFileType = NULL;
  1385. if (fSet)
  1386. {
  1387. TCHAR szFileName[MAX_PATH];
  1388. GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFileName, MAX_PATH);
  1389. CLSID clsid;
  1390. if (S_OK == GetClassFile(szFileName, &clsid))
  1391. OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &lpszFileType);
  1392. }
  1393. if (lpszFileType != NULL)
  1394. {
  1395. SetDlgItemText(hDlg, IDC_IO_FILETYPE, lpszFileType);
  1396. OleStdFree(lpszFileType);
  1397. }
  1398. }
  1399. /*
  1400. * UpdateClassIcon
  1401. *
  1402. * Purpose:
  1403. * Handles LBN_SELCHANGE for the Object Type listbox. On a selection
  1404. * change, we extract an icon from the server handling the currently
  1405. * selected object type using the utility function HIconFromClass.
  1406. * Note that we depend on the behavior of FillClassList to stuff the
  1407. * object class after a tab in the listbox string that we hide from
  1408. * view (see WM_INITDIALOG).
  1409. *
  1410. * Parameters
  1411. * hDlg HWND of the dialog box.
  1412. * lpIO LPINSERTOBJECT pointing to the dialog structure
  1413. * hList HWND of the Object Type listbox.
  1414. *
  1415. * Return Value:
  1416. * None
  1417. */
  1418. static void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList)
  1419. {
  1420. // If Display as Icon is not selected, exit
  1421. if (!(lpIO->dwFlags & IOF_CHECKDISPLAYASICON))
  1422. return;
  1423. /*
  1424. * When we change object type selection, get the new icon for that
  1425. * type into our structure and update it in the display. We use the
  1426. * class in the listbox when Create New is selected or the association
  1427. * with the extension in Create From File.
  1428. */
  1429. DWORD cb = MAX_PATH;
  1430. UINT iSel;
  1431. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  1432. {
  1433. iSel = (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  1434. if (LB_ERR==(int)iSel)
  1435. return;
  1436. // Check to see if we've already got the hMetaPict for this item
  1437. LRESULT dwRet = SendMessage(hList, LB_GETITEMDATA, (WPARAM)iSel, 0L);
  1438. HGLOBAL hMetaPict=(HGLOBAL)dwRet;
  1439. if (hMetaPict)
  1440. {
  1441. // Yep, we've already got it, so just display it and return.
  1442. SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET,
  1443. 0, (LPARAM)hMetaPict);
  1444. return;
  1445. }
  1446. iSel = (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  1447. if (LB_ERR==(int)iSel)
  1448. return;
  1449. // Allocate a string to hold the entire listbox string
  1450. cb = (DWORD)SendMessage(hList, LB_GETTEXTLEN, iSel, 0L);
  1451. }
  1452. LPTSTR pszName = (LPTSTR)OleStdMalloc((cb+1)*sizeof(TCHAR));
  1453. if (NULL == pszName)
  1454. return;
  1455. *pszName = 0;
  1456. // Get the clsid we want.
  1457. HGLOBAL hMetaPict;
  1458. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  1459. {
  1460. // Grab the classname string from the list
  1461. SendMessage(hList, LB_GETTEXT, iSel, (LPARAM)pszName);
  1462. // Set pointer to CLSID (string)
  1463. LPTSTR pszCLSID = PointerToNthField(pszName, 2, '\t');
  1464. // Get CLSID from the string and then accociated icon
  1465. HRESULT hr = CLSIDFromString(pszCLSID, &lpIO->clsid);
  1466. if (FAILED(hr))
  1467. lpIO->clsid = GUID_NULL;
  1468. hMetaPict = OleGetIconOfClass(lpIO->clsid, NULL, TRUE);
  1469. }
  1470. else
  1471. {
  1472. // Get the class from the filename
  1473. GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, pszName, MAX_PATH);
  1474. hMetaPict = OleGetIconOfFile(pszName,
  1475. lpIO->dwFlags & IOF_CHECKLINK ? TRUE : FALSE);
  1476. }
  1477. // Replace the current display with this new one.
  1478. SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET,
  1479. 0, (LPARAM)hMetaPict);
  1480. // Enable or disable "Change Icon" button depending on whether
  1481. // we've got a valid filename or not.
  1482. EnableChangeIconButton(hDlg, hMetaPict ? TRUE : FALSE);
  1483. // Save the hMetaPict so that we won't have to re-create
  1484. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  1485. SendMessage(hList, LB_SETITEMDATA, (WPARAM)iSel, (LPARAM)hMetaPict);
  1486. OleStdFree(pszName);
  1487. }
  1488. /*
  1489. * SetInsertObjectResults
  1490. *
  1491. * Purpose:
  1492. * Centralizes setting of the Result and icon displays in the Insert Object
  1493. * dialog. Handles loading the appropriate string from the module's
  1494. * resources and setting the text, displaying the proper result picture,
  1495. * and showing the proper icon.
  1496. *
  1497. * Parameters:
  1498. * hDlg HWND of the dialog box so we can access controls.
  1499. * lpIO LPINSERTOBJECT in which we assume that the
  1500. * current radiobutton and Display as Icon selections
  1501. * are set. We use the state of those variables to
  1502. * determine which string we use.
  1503. *
  1504. * Return Value:
  1505. * None
  1506. */
  1507. void SetInsertObjectResults(HWND hDlg, LPINSERTOBJECT lpIO)
  1508. {
  1509. /*
  1510. * We need scratch memory for loading the stringtable string, loading
  1511. * the object type from the listbox, and constructing the final string.
  1512. * We therefore allocate three buffers as large as the maximum message
  1513. * length (512) plus the object type, guaranteeing that we have enough
  1514. * in all cases.
  1515. */
  1516. UINT i = (UINT)SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETCURSEL, 0, 0L);
  1517. UINT cch = 512;
  1518. if (i != LB_ERR)
  1519. {
  1520. cch += (UINT)SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETTEXTLEN, i, 0L);
  1521. }
  1522. LPTSTR pszTemp= (LPTSTR)OleStdMalloc((DWORD)(4*cch)*sizeof(TCHAR));
  1523. if (NULL == pszTemp)
  1524. return;
  1525. LPTSTR psz1 = pszTemp;
  1526. LPTSTR psz2 = psz1+cch;
  1527. LPTSTR psz3 = psz2+cch;
  1528. LPTSTR psz4 = psz3+cch;
  1529. BOOL fAsIcon = (0L != (lpIO->dwFlags & IOF_CHECKDISPLAYASICON));
  1530. UINT iImage=0, iString1=0, iString2=0;
  1531. if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL))
  1532. {
  1533. iString1 = fAsIcon ? IDS_IORESULTNEWICON : IDS_IORESULTNEW;
  1534. iString2 = 0;
  1535. iImage = fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
  1536. }
  1537. if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  1538. {
  1539. // Pay attention to Link checkbox
  1540. if (lpIO->dwFlags & IOF_CHECKLINK)
  1541. {
  1542. iString1 = fAsIcon ? IDS_IORESULTLINKFILEICON1 : IDS_IORESULTLINKFILE1;
  1543. iString2 = fAsIcon ? IDS_IORESULTLINKFILEICON2 : IDS_IORESULTLINKFILE2;
  1544. iImage =fAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK;
  1545. }
  1546. else
  1547. {
  1548. iString1 = IDS_IORESULTFROMFILE1;
  1549. iString2 = fAsIcon ? IDS_IORESULTFROMFILEICON2 : IDS_IORESULTFROMFILE2;
  1550. iImage =fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
  1551. }
  1552. }
  1553. // Default is an empty string.
  1554. *psz1=0;
  1555. if (0 != LoadString(_g_hOleStdResInst, iString1, psz1, cch))
  1556. {
  1557. // Load second string, if necessary
  1558. if (0 != iString2 &&
  1559. 0 != LoadString(_g_hOleStdResInst, iString2, psz4, cch))
  1560. {
  1561. lstrcat(psz1, psz4); // concatenate strings together.
  1562. }
  1563. // In Create New, do the extra step of inserting the object type string
  1564. if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL))
  1565. {
  1566. if (i == LB_ERR)
  1567. {
  1568. SetDlgItemText(hDlg, IDC_IO_RESULTTEXT, NULL);
  1569. // Change the image.
  1570. SendDlgItemMessage(hDlg, IDC_IO_RESULTIMAGE, RIM_IMAGESET, RESULTIMAGE_NONE, 0L);
  1571. OleStdFree((LPVOID)pszTemp);
  1572. return;
  1573. }
  1574. *psz2=NULL;
  1575. SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETTEXT, i, (LPARAM)psz2);
  1576. // Null terminate at any tab (before the classname)
  1577. LPTSTR pszT = psz2;
  1578. while (_T('\t') != *pszT && 0 != *pszT)
  1579. pszT++;
  1580. OleDbgAssert(pszT < psz3);
  1581. *pszT=0;
  1582. // Build the string and point psz1 to it.
  1583. wsprintf(psz3, psz1, psz2);
  1584. psz1 = psz3;
  1585. }
  1586. }
  1587. // If LoadString failed, we simply clear out the results (*psz1=0 above)
  1588. SetDlgItemText(hDlg, IDC_IO_RESULTTEXT, psz1);
  1589. // Go change the image and Presto! There you have it.
  1590. SendDlgItemMessage(hDlg, IDC_IO_RESULTIMAGE, RIM_IMAGESET, iImage, 0L);
  1591. OleStdFree((LPVOID)pszTemp);
  1592. }
  1593. /*
  1594. * FValidateInsertFile
  1595. *
  1596. * Purpose:
  1597. * Given a possibly partial pathname from the file edit control,
  1598. * attempt to locate the file and if found, store the full path
  1599. * in the edit control IDC_IO_FILEDISPLAY.
  1600. *
  1601. * Parameters:
  1602. * hDlg HWND of the dialog box.
  1603. * fTellUser BOOL TRUE if function should tell user, FALSE if
  1604. * function should validate silently.
  1605. *
  1606. * Return Value:
  1607. * BOOL TRUE if the file is acceptable, FALSE otherwise.
  1608. */
  1609. BOOL FValidateInsertFile(HWND hDlg, BOOL fTellUser, UINT FAR* lpnErrCode)
  1610. {
  1611. *lpnErrCode = 0;
  1612. /*
  1613. * To validate we attempt OpenFile on the string. If OpenFile
  1614. * fails then we display an error. If not, OpenFile will store
  1615. * the complete path to that file in the OFSTRUCT which we can
  1616. * then stuff in the edit control.
  1617. */
  1618. TCHAR szFile[MAX_PATH];
  1619. if (0 == GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFile, MAX_PATH))
  1620. return FALSE; // #4569 : return FALSE when there is no text in ctl
  1621. // if file is currently open (ie. sharing violation) OleCreateFromFile
  1622. // and OleCreateLinkToFile can still succeed; do not consider it an
  1623. // error.
  1624. if (!DoesFileExist(szFile, MAX_PATH))
  1625. {
  1626. *lpnErrCode = ERROR_FILE_NOT_FOUND;
  1627. if (fTellUser)
  1628. OpenFileError(hDlg, ERROR_FILE_NOT_FOUND, szFile);
  1629. return FALSE;
  1630. }
  1631. // get full pathname, since the file exists
  1632. TCHAR szPath[MAX_PATH];
  1633. LPTSTR lpszDummy;
  1634. GetFullPathName(szFile, sizeof(szPath)/sizeof(TCHAR), szPath, &lpszDummy);
  1635. SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szPath);
  1636. return TRUE;
  1637. }
  1638. /*
  1639. * InsertObjectCleanup
  1640. *
  1641. * Purpose:
  1642. * Clears cached icon metafiles from those stored in the listbox.
  1643. *
  1644. * Parameters:
  1645. * hDlg HWND of the dialog.
  1646. *
  1647. * Return Value:
  1648. * None
  1649. */
  1650. void InsertObjectCleanup(HWND hDlg)
  1651. {
  1652. HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
  1653. UINT iItems= (UINT)SendMessage(hList, LB_GETCOUNT, 0, 0L);
  1654. for (UINT i = 0; i < iItems; i++)
  1655. {
  1656. LRESULT dwRet = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
  1657. HGLOBAL hMetaPict=(HGLOBAL)dwRet;
  1658. if (hMetaPict)
  1659. OleUIMetafilePictIconFree(hMetaPict);
  1660. }
  1661. }
  1662. void EnableChangeIconButton(HWND hDlg, BOOL fEnable)
  1663. {
  1664. HRESULT hr = S_OK;
  1665. if(fEnable){
  1666. HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
  1667. int iCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  1668. CLSID clsid = {0};
  1669. if (1 == IsDlgButtonChecked(hDlg, IDC_IO_CREATENEW))
  1670. {
  1671. LPTSTR pszString = (LPTSTR)OleStdMalloc(
  1672. OLEUI_CCHKEYMAX_SIZE + OLEUI_CCHCLSIDSTRING_SIZE);
  1673. if(NULL == pszString)
  1674. {
  1675. fEnable = FALSE;
  1676. goto CLEANUP;
  1677. }
  1678. SendMessage(hList, LB_GETTEXT, iCurSel, (LPARAM)pszString);
  1679. if(0 == *pszString)
  1680. {
  1681. fEnable = FALSE;
  1682. OleStdFree((LPVOID)pszString);
  1683. goto CLEANUP;
  1684. }
  1685. LPTSTR pszCLSID = PointerToNthField(pszString, 2, '\t');
  1686. if(NULL == pszCLSID || 0 == *pszCLSID)
  1687. {
  1688. fEnable = FALSE;
  1689. OleStdFree((LPVOID)pszString);
  1690. goto CLEANUP;
  1691. }
  1692. hr = CLSIDFromString(pszCLSID, &clsid);
  1693. OleStdFree((LPVOID)pszString);
  1694. if(FAILED(hr))
  1695. {
  1696. fEnable = FALSE;
  1697. }
  1698. }
  1699. else // IOF_SELECTCREATEFROMFILE
  1700. {
  1701. TCHAR szFileName[MAX_PATH] = {0};
  1702. GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFileName, MAX_PATH);
  1703. if (S_OK != GetClassFile(szFileName, &clsid))
  1704. {
  1705. int istrlen = lstrlen(szFileName);
  1706. LPTSTR lpszExtension = szFileName + istrlen -1;
  1707. while (lpszExtension > szFileName &&
  1708. *lpszExtension != '.')
  1709. {
  1710. lpszExtension = CharPrev(szFileName, lpszExtension);
  1711. }
  1712. *szFileName = 0;
  1713. GetAssociatedExecutable(lpszExtension, szFileName, sizeof(szFileName)/sizeof(szFileName[0]));
  1714. if(0 == *szFileName){
  1715. fEnable = FALSE;
  1716. }
  1717. }
  1718. }
  1719. }
  1720. CLEANUP:
  1721. StandardEnableDlgItem(hDlg, IDC_IO_CHANGEICON, fEnable);
  1722. }