Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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