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.

1724 lines
58 KiB

  1. /*
  2. * INSOBJ.C
  3. *
  4. * Implements the OleUIInsertObject function which invokes the complete
  5. * Insert Object dialog. Makes use of the OleChangeIcon function in
  6. * ICON.C.
  7. *
  8. * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9. */
  10. #define STRICT 1
  11. #include "ole2ui.h"
  12. #include <commdlg.h>
  13. #include <memory.h>
  14. #include <direct.h>
  15. #include <malloc.h>
  16. #include <dos.h>
  17. #include <stdlib.h>
  18. #include "common.h"
  19. #include "utility.h"
  20. #include "icon.h"
  21. #include "insobj.h"
  22. #include "resimage.h"
  23. #include "iconbox.h"
  24. #include "geticon.h"
  25. #define IS_FILENAME_DELIM(c) ( (c) == TEXT('\\') || (c) == TEXT('/') || (c) == TEXT(':') )
  26. /*
  27. * OleUIInsertObject
  28. *
  29. * Purpose:
  30. * Invokes the standard OLE Insert Object dialog box allowing the
  31. * user to select an object source and classname as well as the option
  32. * to display the object as itself or as an icon.
  33. *
  34. * Parameters:
  35. * lpIO LPOLEUIINSERTOBJECT pointing to the in-out structure
  36. * for this dialog.
  37. *
  38. * Return Value:
  39. * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise
  40. * an error value.
  41. */
  42. STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT lpIO)
  43. {
  44. UINT uRet;
  45. HGLOBAL hMemDlg=NULL;
  46. HRESULT hrErr;
  47. uRet=UStandardValidation((LPOLEUISTANDARD)lpIO, sizeof(OLEUIINSERTOBJECT)
  48. , &hMemDlg);
  49. if (OLEUI_SUCCESS!=uRet)
  50. return uRet;
  51. //Now we can do Insert Object specific validation.
  52. // NULL is NOT valid for lpszFile
  53. if ( (NULL == lpIO->lpszFile)
  54. || (IsBadReadPtr(lpIO->lpszFile, lpIO->cchFile))
  55. || (IsBadWritePtr(lpIO->lpszFile, lpIO->cchFile)) )
  56. uRet=OLEUI_IOERR_LPSZFILEINVALID;
  57. if (NULL != lpIO->lpszFile
  58. && (lpIO->cchFile <= 0 || lpIO->cchFile > OLEUI_CCHPATHMAX_SIZE))
  59. uRet=OLEUI_IOERR_CCHFILEINVALID;
  60. if (0!=lpIO->cClsidExclude)
  61. {
  62. if (NULL!=lpIO->lpClsidExclude && IsBadReadPtr(lpIO->lpClsidExclude
  63. , lpIO->cClsidExclude*sizeof(CLSID)))
  64. uRet=OLEUI_IOERR_LPCLSIDEXCLUDEINVALID;
  65. }
  66. //If we have flags to create any object, validate necessary data.
  67. if (lpIO->dwFlags & (IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT | IOF_CREATELINKOBJECT))
  68. {
  69. if (NULL!=lpIO->lpFormatEtc
  70. && IsBadReadPtr(lpIO->lpFormatEtc, sizeof(FORMATETC)))
  71. uRet=OLEUI_IOERR_LPFORMATETCINVALID;
  72. if (NULL!=lpIO->ppvObj && IsBadWritePtr(lpIO->ppvObj, sizeof(LPVOID)))
  73. uRet=OLEUI_IOERR_PPVOBJINVALID;
  74. if (NULL!=lpIO->lpIOleClientSite
  75. && IsBadReadPtr(lpIO->lpIOleClientSite->lpVtbl, sizeof(IOleClientSiteVtbl)))
  76. uRet=OLEUI_IOERR_LPIOLECLIENTSITEINVALID;
  77. if (NULL!=lpIO->lpIStorage
  78. && IsBadReadPtr(lpIO->lpIStorage->lpVtbl, sizeof(IStorageVtbl)))
  79. uRet=OLEUI_IOERR_LPISTORAGEINVALID;
  80. }
  81. if (OLEUI_ERR_STANDARDMIN <= uRet)
  82. {
  83. if (NULL!=hMemDlg)
  84. FreeResource(hMemDlg);
  85. return uRet;
  86. }
  87. //Now that we've validated everything, we can invoke the dialog.
  88. uRet=UStandardInvocation(InsertObjectDialogProc, (LPOLEUISTANDARD)lpIO
  89. , hMemDlg, MAKEINTRESOURCE(IDD_INSERTOBJECT));
  90. //Stop here if we cancelled or had an error.
  91. if (OLEUI_SUCCESS !=uRet && OLEUI_OK!=uRet)
  92. return uRet;
  93. /*
  94. * If any of the flags specify that we're to create objects on return
  95. * from this dialog, then do so. If we encounter an error in this
  96. * processing, we return OLEUI_IOERR_SCODEHASERROR. Since the
  97. * three select flags are mutually exclusive, we don't have to
  98. * if...else here, just if each case (keeps things cleaner that way).
  99. */
  100. lpIO->sc=S_OK;
  101. //Check if Create New was selected and we have IOF_CREATENEWOBJECT
  102. if ((lpIO->dwFlags & IOF_SELECTCREATENEW) && (lpIO->dwFlags & IOF_CREATENEWOBJECT))
  103. {
  104. hrErr=OleCreate(&lpIO->clsid, &lpIO->iid, lpIO->oleRender
  105. , lpIO->lpFormatEtc, lpIO->lpIOleClientSite, lpIO->lpIStorage
  106. , lpIO->ppvObj);
  107. lpIO->sc = GetScode(hrErr);
  108. }
  109. //Try Create From File
  110. if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE))
  111. {
  112. if (!(lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATEFILEOBJECT))
  113. {
  114. hrErr=OleCreateFromFileA(&CLSID_NULL, lpIO->lpszFile, &lpIO->iid
  115. , lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite
  116. , lpIO->lpIStorage, lpIO->ppvObj);
  117. lpIO->sc = GetScode(hrErr);
  118. }
  119. if ((lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATELINKOBJECT))
  120. {
  121. hrErr=OleCreateLinkToFileA(lpIO->lpszFile, &lpIO->iid
  122. , lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite
  123. , lpIO->lpIStorage, lpIO->ppvObj);
  124. lpIO->sc = GetScode(hrErr);
  125. }
  126. }
  127. //If we tried but failed a create option, then return the appropriate error
  128. if (S_OK!=lpIO->sc)
  129. uRet=OLEUI_IOERR_SCODEHASERROR;
  130. return uRet;
  131. }
  132. /*
  133. * InsertObjectDialogProc
  134. *
  135. * Purpose:
  136. * Implements the OLE Insert Object dialog as invoked through the
  137. * OleUIInsertObject function.
  138. */
  139. BOOL CALLBACK EXPORT InsertObjectDialogProc(HWND hDlg, UINT iMsg
  140. , WPARAM wParam, LPARAM lParam)
  141. {
  142. LPOLEUIINSERTOBJECT lpOIO;
  143. LPINSERTOBJECT lpIO;
  144. OLEUICHANGEICON ci;
  145. UINT i;
  146. BOOL fCheck=FALSE;
  147. UINT uRet=0;
  148. //Declare Win16/Win32 compatible WM_COMMAND parameters.
  149. COMMANDPARAMS(wID, wCode, hWndMsg);
  150. //This will fail under WM_INITDIALOG, where we allocate it.
  151. lpIO=(LPINSERTOBJECT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
  152. //If the hook processed the message, we're done.
  153. if (0!=uRet)
  154. return (BOOL)uRet;
  155. //Process help message from Change Icon
  156. if (iMsg==uMsgHelp)
  157. {
  158. PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, wParam, lParam);
  159. return FALSE;
  160. }
  161. //Process the temination message
  162. if (iMsg==uMsgEndDialog)
  163. {
  164. InsertObjectCleanup(hDlg);
  165. StandardCleanup(lpIO, hDlg);
  166. EndDialog(hDlg, wParam);
  167. return TRUE;
  168. }
  169. switch (iMsg)
  170. {
  171. case WM_INITDIALOG:
  172. return FInsertObjectInit(hDlg, wParam, lParam);
  173. case WM_COMMAND:
  174. switch (wID)
  175. {
  176. case ID_IO_CREATENEW:
  177. FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATENEW);
  178. break;
  179. case ID_IO_CREATEFROMFILE:
  180. FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATEFROMFILE);
  181. break;
  182. case ID_IO_LINKFILE:
  183. fCheck=IsDlgButtonChecked(hDlg, wID);
  184. if (fCheck)
  185. lpIO->dwFlags |=IOF_CHECKLINK;
  186. else
  187. lpIO->dwFlags &=~IOF_CHECKLINK;
  188. //Results change here, so be sure to update it.
  189. SetInsertObjectResults(hDlg, lpIO);
  190. UpdateClassIcon(hDlg, lpIO, NULL);
  191. break;
  192. case ID_IO_OBJECTTYPELIST:
  193. switch (wCode)
  194. {
  195. case LBN_SELCHANGE:
  196. UpdateClassIcon(hDlg, lpIO, hWndMsg);
  197. SetInsertObjectResults(hDlg, lpIO);
  198. break;
  199. case LBN_DBLCLK:
  200. //Same as pressing OK.
  201. SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
  202. break;
  203. }
  204. break;
  205. case ID_IO_FILEDISPLAY:
  206. //If there are characters, enable OK and Display As Icon
  207. if (EN_CHANGE==wCode)
  208. {
  209. lpIO->fFileDirty = TRUE;
  210. lpIO->fFileValid = FALSE;
  211. lpIO->fFileSelected=
  212. (0L!=SendMessage(hWndMsg, EM_LINELENGTH, 0, 0L));
  213. EnableWindow(GetDlgItem(hDlg, ID_IO_LINKFILE), lpIO->fFileSelected);
  214. EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), lpIO->fFileSelected);
  215. EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), lpIO->fFileSelected);
  216. EnableWindow(GetDlgItem(hDlg, IDOK), lpIO->fFileSelected);
  217. }
  218. if (EN_KILLFOCUS==wCode && NULL!=lpIO)
  219. {
  220. if (FValidateInsertFile(hDlg,FALSE,&lpIO->nErrCode)) {
  221. lpIO->fFileDirty = FALSE;
  222. lpIO->fFileValid = TRUE;
  223. UpdateClassIcon(hDlg, lpIO, NULL);
  224. UpdateClassType(hDlg, lpIO, TRUE);
  225. } else {
  226. lpIO->fFileDirty = FALSE;
  227. lpIO->fFileValid = FALSE;
  228. UpdateClassType(hDlg, lpIO, FALSE);
  229. }
  230. }
  231. break;
  232. case ID_IO_DISPLAYASICON:
  233. fCheck=IsDlgButtonChecked(hDlg, wID);
  234. EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), fCheck);
  235. if (fCheck)
  236. lpIO->dwFlags |=IOF_CHECKDISPLAYASICON;
  237. else
  238. lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
  239. //Update the internal flag based on this checking
  240. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  241. lpIO->fAsIconNew=fCheck;
  242. else
  243. lpIO->fAsIconFile=fCheck;
  244. //Re-read the class icon on Display checked
  245. if (fCheck)
  246. {
  247. if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  248. {
  249. if (FValidateInsertFile(hDlg, TRUE,&lpIO->nErrCode))
  250. {
  251. lpIO->fFileDirty = FALSE;
  252. lpIO->fFileValid = TRUE;
  253. UpdateClassIcon(hDlg, lpIO,
  254. GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
  255. UpdateClassType(hDlg, lpIO, TRUE);
  256. }
  257. else
  258. {
  259. HWND hWndEC;
  260. lpIO->fAsIconFile= FALSE;
  261. lpIO->fFileDirty = FALSE;
  262. lpIO->fFileValid = FALSE;
  263. SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, 0, 0L);
  264. UpdateClassType(hDlg, lpIO, FALSE);
  265. lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
  266. CheckDlgButton(hDlg, ID_IO_DISPLAYASICON, 0);
  267. hWndEC = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
  268. SetFocus(hWndEC);
  269. SendMessage(hWndEC, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
  270. return TRUE;
  271. }
  272. }
  273. else
  274. UpdateClassIcon(hDlg, lpIO,
  275. GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
  276. }
  277. //Results change here, so be sure to update it.
  278. SetInsertObjectResults(hDlg, lpIO);
  279. /*
  280. * Show or hide controls as appropriate. Do the icon
  281. * display last because it will take some time to repaint.
  282. * If we do it first then the dialog looks too sluggish.
  283. */
  284. i=(fCheck) ? SW_SHOWNORMAL : SW_HIDE;
  285. StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, i);
  286. StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, i);
  287. break;
  288. case ID_IO_CHANGEICON:
  289. {
  290. LPMALLOC pIMalloc;
  291. HWND hList;
  292. LPTSTR pszString, pszCLSID;
  293. int iCurSel;
  294. // if we're in SELECTCREATEFROMFILE mode, then we need to Validate
  295. // the contents of the edit control first.
  296. if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  297. {
  298. if ( lpIO->fFileDirty
  299. && !FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode) )
  300. {
  301. HWND hWndEC;
  302. lpIO->fFileDirty = TRUE;
  303. hWndEC = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
  304. SetFocus(hWndEC);
  305. SendMessage(hWndEC, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
  306. return TRUE;
  307. }
  308. else
  309. lpIO->fFileDirty = FALSE;
  310. }
  311. //Initialize the structure for the hook.
  312. _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci));
  313. ci.hMetaPict=(HGLOBAL)SendDlgItemMessage(hDlg
  314. , ID_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  315. ci.cbStruct =sizeof(ci);
  316. ci.hWndOwner=hDlg;
  317. ci.dwFlags =CIF_SELECTCURRENT;
  318. if (lpIO->dwFlags & IOF_SHOWHELP)
  319. ci.dwFlags |= CIF_SHOWHELP;
  320. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  321. {
  322. // Initialize clsid...
  323. if (NOERROR != CoGetMalloc(MEMCTX_TASK, &pIMalloc))
  324. return FALSE;
  325. pszString = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc,
  326. OLEUI_CCHKEYMAX_SIZE +
  327. OLEUI_CCHCLSIDSTRING_SIZE);
  328. hList = GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST);
  329. iCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  330. SendMessage(hList, LB_GETTEXT, iCurSel, (LONG)pszString);
  331. pszCLSID = PointerToNthField(pszString, 2, TEXT('\t'));
  332. CLSIDFromStringA((LPTSTR)pszCLSID, (LPCLSID)&(ci.clsid));
  333. pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszString);
  334. pIMalloc->lpVtbl->Release(pIMalloc);
  335. }
  336. else // IOF_SELECTCREATEFROMFILE
  337. {
  338. TCHAR szFileName[OLEUI_CCHPATHMAX];
  339. GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szFileName, OLEUI_CCHPATHMAX);
  340. if (NOERROR != GetClassFileA(szFileName, (LPCLSID)&(ci.clsid)))
  341. {
  342. LPTSTR lpszExtension;
  343. int istrlen;
  344. istrlen = lstrlen(szFileName);
  345. lpszExtension = (LPTSTR)szFileName + istrlen -1;
  346. while ( (lpszExtension > szFileName) &&
  347. (*lpszExtension != TEXT('.')) )
  348. lpszExtension--;
  349. GetAssociatedExecutable(lpszExtension, (LPTSTR)ci.szIconExe);
  350. ci.cchIconExe = lstrlen(ci.szIconExe);
  351. ci.dwFlags |= CIF_USEICONEXE;
  352. }
  353. }
  354. //Let the hook in to customize Change Icon if desired.
  355. uRet=UStandardHook(lpIO, hDlg, uMsgChangeIcon
  356. , 0, (LONG)(LPTSTR)&ci);
  357. if (0==uRet)
  358. uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci));
  359. //Update the display and itemdata if necessary.
  360. if (0!=uRet)
  361. {
  362. /*
  363. * OleUIChangeIcon will have already freed our
  364. * current hMetaPict that we passed in when OK is
  365. * pressed in that dialog. So we use 0L as lParam
  366. * here so the IconBox doesn't try to free the
  367. * metafilepict again.
  368. */
  369. SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET
  370. , (WPARAM)ci.hMetaPict, 0L);
  371. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  372. SendMessage(hList, LB_SETITEMDATA, iCurSel, ci.hMetaPict);
  373. }
  374. }
  375. break;
  376. case ID_IO_FILE:
  377. {
  378. /*
  379. * To allow the hook to customize the browse dialog, we
  380. * send OLEUI_MSG_BROWSE. If the hook returns FALSE
  381. * we use the default, otherwise we trust that it retrieved
  382. * a filename for us. This mechanism prevents hooks from
  383. * trapping ID_IO_BROWSE to customize the dialog and from
  384. * trying to figure out what we do after we have the name.
  385. */
  386. TCHAR szTemp[OLEUI_CCHPATHMAX];
  387. TCHAR szInitialDir[OLEUI_CCHPATHMAX];
  388. DWORD dwOfnFlags;
  389. int nChars;
  390. BOOL fUseInitialDir = FALSE;
  391. nChars = GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szTemp, OLEUI_CCHPATHMAX);
  392. if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
  393. {
  394. int istrlen;
  395. GetFileTitle((LPTSTR)szTemp, lpIO->szFile, OLEUI_CCHPATHMAX);
  396. istrlen = lstrlen(lpIO->szFile);
  397. LSTRCPYN((LPTSTR)szInitialDir, szTemp, nChars - istrlen);
  398. fUseInitialDir = TRUE;
  399. }
  400. else // file name isn't valid...lop off end of szTemp to get a
  401. // valid directory
  402. {
  403. #if defined( WIN32 )
  404. TCHAR szBuffer[OLEUI_CCHPATHMAX];
  405. DWORD Attribs;
  406. LSTRCPYN(szBuffer, szTemp, OLEUI_CCHPATHMAX-1);
  407. szBuffer[OLEUI_CCHPATHMAX-1] = TEXT('\0');
  408. if (TEXT('\\') == szBuffer[nChars-1])
  409. szBuffer[nChars-1] = TEXT('\0');
  410. Attribs = GetFileAttributes(szBuffer);
  411. if (Attribs != 0xffffffff &&
  412. (Attribs & FILE_ATTRIBUTE_DIRECTORY) )
  413. {
  414. lstrcpy(szInitialDir, (LPTSTR)szBuffer);
  415. fUseInitialDir = TRUE;
  416. }
  417. #else
  418. static TCHAR szBuffer[OLEUI_CCHPATHMAX];
  419. static int attrib ;
  420. LSTRCPYN(szBuffer, szTemp, OLEUI_CCHPATHMAX-1);
  421. szBuffer[OLEUI_CCHPATHMAX-1] = TEXT('\0');
  422. AnsiToOem(szBuffer, szBuffer);
  423. #if defined( OBSOLETE ) // fix bug# 3575
  424. if (TEXT('\\') == szBuffer[nChars-1])
  425. szBuffer[nChars-1] = TEXT('\0');
  426. if(0 == _dos_getfileattr(szBuffer, &attrib))
  427. #endif // OBSOLETE
  428. {
  429. lstrcpy(szInitialDir, (LPTSTR)szBuffer);
  430. fUseInitialDir = TRUE;
  431. }
  432. #endif
  433. *lpIO->szFile = TEXT('\0');
  434. }
  435. uRet=UStandardHook(lpIO, hDlg, uMsgBrowse
  436. , OLEUI_CCHPATHMAX_SIZE, (LPARAM)(LPSTR)lpIO->szFile);
  437. dwOfnFlags = OFN_FILEMUSTEXIST;
  438. if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP)
  439. dwOfnFlags |= OFN_SHOWHELP;
  440. if (0==uRet)
  441. uRet=(UINT)Browse(hDlg,
  442. lpIO->szFile,
  443. fUseInitialDir ? (LPTSTR)szInitialDir : NULL,
  444. OLEUI_CCHPATHMAX_SIZE,
  445. IDS_FILTERS,
  446. dwOfnFlags);
  447. //Only update if the file changed.
  448. if (0!=uRet && 0!=lstrcmpi(szTemp, lpIO->szFile))
  449. {
  450. SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, lpIO->szFile);
  451. lpIO->fFileSelected=TRUE;
  452. if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
  453. {
  454. lpIO->fFileDirty = FALSE;
  455. lpIO->fFileValid = TRUE;
  456. UpdateClassIcon(hDlg, lpIO, NULL);
  457. UpdateClassType(hDlg, lpIO, TRUE);
  458. // auto set OK to be default button if valid file
  459. SendMessage(hDlg, DM_SETDEFID,
  460. (WPARAM)GetDlgItem(hDlg, IDOK), 0L);
  461. SetFocus(GetDlgItem(hDlg, IDOK));
  462. }
  463. else // filename is invalid - set focus back to ec
  464. {
  465. HWND hWnd;
  466. lpIO->fFileDirty = FALSE;
  467. lpIO->fFileValid = FALSE;
  468. hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
  469. SetFocus(hWnd);
  470. SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
  471. }
  472. //Once we have a file, Display As Icon is always enabled
  473. EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), TRUE);
  474. //As well as OK
  475. EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
  476. }
  477. }
  478. break;
  479. case IDOK:
  480. {
  481. HWND hListBox;
  482. WORD iCurSel;
  483. TCHAR szBuffer[OLEUI_CCHKEYMAX + OLEUI_CCHCLSIDSTRING];
  484. LPTSTR lpszCLSID;
  485. if ((HWND)(LOWORD(lParam)) != GetFocus())
  486. SetFocus((HWND)(LOWORD(lParam)));
  487. // If the file name is clean (already validated), or
  488. // if Create New is selected, then we can skip this part.
  489. if ( (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  490. && (TRUE == lpIO->fFileDirty) )
  491. {
  492. if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
  493. {
  494. lpIO->fFileDirty = FALSE;
  495. lpIO->fFileValid = TRUE;
  496. UpdateClassIcon(hDlg, lpIO, NULL);
  497. UpdateClassType(hDlg, lpIO, TRUE);
  498. }
  499. else // filename is invalid - set focus back to ec
  500. {
  501. HWND hWnd;
  502. lpIO->fFileDirty = FALSE;
  503. lpIO->fFileValid = FALSE;
  504. hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
  505. SetFocus(hWnd);
  506. SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
  507. UpdateClassType(hDlg, lpIO, FALSE);
  508. }
  509. return TRUE; // eat this message
  510. }
  511. else if ( (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  512. && (FALSE == lpIO->fFileValid) )
  513. {
  514. // filename is invalid - set focus back to ec
  515. HWND hWnd;
  516. TCHAR szFile[OLEUI_CCHPATHMAX];
  517. if (0!=GetDlgItemText(hDlg, ID_IO_FILEDISPLAY,
  518. szFile, OLEUI_CCHPATHMAX))
  519. {
  520. OpenFileError(hDlg, lpIO->nErrCode, szFile);
  521. }
  522. lpIO->fFileDirty = FALSE;
  523. lpIO->fFileValid = FALSE;
  524. hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
  525. SetFocus(hWnd);
  526. SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
  527. UpdateClassType(hDlg, lpIO, FALSE);
  528. return TRUE; // eat this message
  529. }
  530. //Copy the necessary information back to the original struct
  531. lpOIO=lpIO->lpOIO;
  532. lpOIO->dwFlags=lpIO->dwFlags;
  533. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  534. {
  535. hListBox=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST);
  536. iCurSel=(WORD)SendMessage(hListBox, LB_GETCURSEL, 0, 0);
  537. if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
  538. {
  539. lpOIO->hMetaPict=(HGLOBAL)SendMessage(hListBox,
  540. LB_GETITEMDATA, iCurSel, 0L);
  541. /*
  542. * Set the item data to 0 here so that the cleanup
  543. * code doesn't delete the metafile.
  544. */
  545. SendMessage(hListBox, LB_SETITEMDATA, iCurSel, 0L);
  546. }
  547. else
  548. lpOIO->hMetaPict = (HGLOBAL)NULL;
  549. SendMessage(hListBox, LB_GETTEXT, iCurSel
  550. , (LPARAM)(LPTSTR)szBuffer);
  551. lpszCLSID=PointerToNthField((LPTSTR)szBuffer, 2, TEXT('\t'));
  552. CLSIDFromStringA(lpszCLSID, &lpOIO->clsid);
  553. }
  554. else // IOF_SELECTCREATEFROMFILE
  555. {
  556. if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
  557. {
  558. // get metafile here
  559. lpOIO->hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
  560. ID_IO_ICONDISPLAY,
  561. IBXM_IMAGEGET,
  562. 0, 0L);
  563. }
  564. else
  565. lpOIO->hMetaPict = (HGLOBAL)NULL;
  566. }
  567. GetDlgItemText(hDlg, ID_IO_FILEDISPLAY,
  568. lpIO->szFile, lpOIO->cchFile);
  569. LSTRCPYN(lpOIO->lpszFile, lpIO->szFile, lpOIO->cchFile);
  570. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  571. }
  572. break;
  573. case IDCANCEL:
  574. SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
  575. break;
  576. case ID_OLEUIHELP:
  577. PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp
  578. , (WPARAM)hDlg, MAKELPARAM(IDD_INSERTOBJECT, 0));
  579. break;
  580. }
  581. break;
  582. default:
  583. {
  584. if (lpIO && iMsg == lpIO->nBrowseHelpID) {
  585. PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp,
  586. (WPARAM)hDlg, MAKELPARAM(IDD_INSERTFILEBROWSE, 0));
  587. }
  588. }
  589. break;
  590. }
  591. return FALSE;
  592. }
  593. /*
  594. * FInsertObjectInit
  595. *
  596. * Purpose:
  597. * WM_INITIDIALOG handler for the Insert Object dialog box.
  598. *
  599. * Parameters:
  600. * hDlg HWND of the dialog
  601. * wParam WPARAM of the message
  602. * lParam LPARAM of the message
  603. *
  604. * Return Value:
  605. * BOOL Value to return for WM_INITDIALOG.
  606. */
  607. BOOL FInsertObjectInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
  608. {
  609. LPOLEUIINSERTOBJECT lpOIO;
  610. LPINSERTOBJECT lpIO;
  611. RECT rc;
  612. DWORD dw;
  613. HFONT hFont;
  614. HWND hList;
  615. UINT u;
  616. BOOL fCheck;
  617. CHAR *pch; // pointer to current working directory
  618. // ANSI string (to use with _getcwd)
  619. //1. Copy the structure at lParam into our instance memory.
  620. lpIO=(LPINSERTOBJECT)LpvStandardInit(hDlg, sizeof(INSERTOBJECT), TRUE, &hFont);
  621. //PvStandardInit send a termination to us already.
  622. if (NULL==lpIO)
  623. return FALSE;
  624. lpOIO=(LPOLEUIINSERTOBJECT)lParam;
  625. //2. Save the original pointer and copy necessary information.
  626. lpIO->lpOIO =lpOIO;
  627. lpIO->dwFlags=lpOIO->dwFlags;
  628. lpIO->clsid =lpOIO->clsid;
  629. if ( (lpOIO->lpszFile) && (TEXT('\0') != *lpOIO->lpszFile) )
  630. LSTRCPYN((LPTSTR)lpIO->szFile, lpOIO->lpszFile, OLEUI_CCHPATHMAX);
  631. else
  632. *(lpIO->szFile) = TEXT('\0');
  633. lpIO->hMetaPictFile = (HGLOBAL)NULL;
  634. //3. If we got a font, send it to the necessary controls.
  635. if (NULL!=hFont)
  636. {
  637. SendDlgItemMessage(hDlg, ID_IO_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
  638. SendDlgItemMessage(hDlg, ID_IO_FILETYPE, WM_SETFONT, (WPARAM)hFont, 0L);
  639. }
  640. //4. Fill the Object Type listbox with entries from the reg DB.
  641. hList=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST);
  642. UFillClassList(hList, lpOIO->cClsidExclude, lpOIO->lpClsidExclude
  643. , (BOOL)(lpOIO->dwFlags & IOF_VERIFYSERVERSEXIST));
  644. //Set the tab width in the list to push all the tabs off the side.
  645. GetClientRect(hList, &rc);
  646. dw=GetDialogBaseUnits();
  647. rc.right =(8*rc.right)/LOWORD(dw); //Convert pixels to 2x dlg units.
  648. SendMessage(hList, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&rc.right);
  649. //5. Initilize the file name display to cwd if we don't have any name.
  650. if (TEXT('\0') == *(lpIO->szFile))
  651. {
  652. TCHAR tch[OLEUI_CCHPATHMAX];
  653. pch=_getcwd(NULL, OLEUI_CCHPATHMAX);
  654. if (*(pch+strlen(pch)-1) != '\\')
  655. strcat(pch, "\\"); // put slash on end of cwd
  656. #ifdef UNICODE
  657. mbstowcs(tch, pch, OLEUI_CCHPATHMAX);
  658. #else
  659. strcpy(tch, pch);
  660. #endif
  661. SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, tch);
  662. lpIO->fFileDirty = TRUE; // cwd is not a valid filename
  663. #ifndef __TURBOC__
  664. free(pch);
  665. #endif
  666. }
  667. else
  668. {
  669. SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, lpIO->szFile);
  670. if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
  671. lpIO->fFileDirty = FALSE;
  672. else
  673. lpIO->fFileDirty = TRUE;
  674. }
  675. //6. Initialize the selected type radiobutton.
  676. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  677. {
  678. StandardShowDlgItem(hDlg, ID_IO_FILETEXT, SW_HIDE);
  679. StandardShowDlgItem(hDlg, ID_IO_FILETYPE, SW_HIDE);
  680. StandardShowDlgItem(hDlg, ID_IO_FILEDISPLAY, SW_HIDE);
  681. StandardShowDlgItem(hDlg, ID_IO_FILE, SW_HIDE);
  682. StandardShowDlgItem(hDlg, ID_IO_LINKFILE, SW_HIDE);
  683. CheckRadioButton(hDlg, ID_IO_CREATENEW, ID_IO_CREATEFROMFILE, ID_IO_CREATENEW);
  684. lpIO->fAsIconNew=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON));
  685. SetFocus(hList);
  686. }
  687. else
  688. {
  689. /*
  690. * Use pszType as the initial File. If there's no initial
  691. * file then we have to remove any check from Display As
  692. * Icon. We also check Link if so indicated for this option.
  693. */
  694. StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPELIST, SW_HIDE);
  695. StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPETEXT, SW_HIDE);
  696. // Don't preselect display as icon if the filename isn't valid
  697. if (TRUE == lpIO->fFileDirty)
  698. lpIO->dwFlags &= ~(IOF_CHECKDISPLAYASICON);
  699. if (IOF_DISABLELINK & lpIO->dwFlags)
  700. StandardShowDlgItem(hDlg, ID_IO_LINKFILE, SW_HIDE);
  701. else
  702. {
  703. CheckDlgButton(hDlg, ID_IO_LINKFILE
  704. , (BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKLINK)));
  705. }
  706. CheckRadioButton(hDlg, ID_IO_CREATENEW, ID_IO_CREATEFROMFILE, ID_IO_CREATEFROMFILE);
  707. lpIO->fAsIconFile=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON));
  708. SetFocus(GetDlgItem(hDlg, ID_IO_FILEDISPLAY));
  709. }
  710. //7. Initialize the Display as Icon state
  711. fCheck=(BOOL)(lpIO->dwFlags & IOF_CHECKDISPLAYASICON);
  712. u=fCheck ? SW_SHOWNORMAL : SW_HIDE;
  713. StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, u);
  714. StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, u);
  715. CheckDlgButton(hDlg, ID_IO_DISPLAYASICON, fCheck);
  716. //8. Show or hide the help button
  717. if (!(lpIO->dwFlags & IOF_SHOWHELP))
  718. StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
  719. //9. Initialize the result display
  720. UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
  721. SetInsertObjectResults(hDlg, lpIO);
  722. //10. Change the caption
  723. if (NULL!=lpOIO->lpszCaption)
  724. SetWindowText(hDlg, lpOIO->lpszCaption);
  725. //11. Hide all DisplayAsIcon related controls if it should be disabled
  726. if ( lpIO->dwFlags & IOF_DISABLEDISPLAYASICON ) {
  727. StandardShowDlgItem(hDlg, ID_IO_DISPLAYASICON, SW_HIDE);
  728. StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, SW_HIDE);
  729. StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, SW_HIDE);
  730. }
  731. lpIO->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING);
  732. //All Done: call the hook with lCustData
  733. UStandardHook(lpIO, hDlg, WM_INITDIALOG, wParam, lpOIO->lCustData);
  734. /*
  735. * We either set focus to the listbox or the edit control. In either
  736. * case we don't want Windows to do any SetFocus, so we return FALSE.
  737. */
  738. return FALSE;
  739. }
  740. /*
  741. * UFillClassList
  742. *
  743. * Purpose:
  744. * Enumerates available OLE object classes from the registration
  745. * database and fills a listbox with those names.
  746. *
  747. * Note that this function removes any prior contents of the listbox.
  748. *
  749. * Parameters:
  750. * hList HWND to the listbox to fill.
  751. * cIDEx UINT number of CLSIDs to exclude in lpIDEx
  752. * lpIDEx LPCLSID to CLSIDs to leave out of the listbox.
  753. * fVerify BOOL indicating if we are to validate existence of
  754. * servers before putting them in the list.
  755. *
  756. * Return Value:
  757. * UINT Number of strings added to the listbox, -1 on failure.
  758. */
  759. UINT UFillClassList(HWND hList, UINT cIDEx, LPCLSID lpIDEx, BOOL fVerify)
  760. {
  761. DWORD dw;
  762. UINT cStrings=0;
  763. UINT i;
  764. UINT cch;
  765. HKEY hKey;
  766. LONG lRet;
  767. HFILE hFile;
  768. OFSTRUCT of;
  769. BOOL fExclude;
  770. LPMALLOC pIMalloc;
  771. LPTSTR pszExec;
  772. LPTSTR pszClass;
  773. LPTSTR pszKey;
  774. LPTSTR pszID;
  775. CLSID clsid;
  776. //Get some work buffers
  777. if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc))
  778. return (UINT)-1;
  779. pszExec=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHKEYMAX_SIZE*4);
  780. if (NULL==pszExec)
  781. {
  782. pIMalloc->lpVtbl->Release(pIMalloc);
  783. return (UINT)-1;
  784. }
  785. pszClass=pszExec+OLEUI_CCHKEYMAX;
  786. pszKey=pszClass+OLEUI_CCHKEYMAX;
  787. pszID=pszKey+OLEUI_CCHKEYMAX;
  788. //Open up the root key.
  789. lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
  790. if ((LONG)ERROR_SUCCESS!=lRet)
  791. {
  792. pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszExec);
  793. pIMalloc->lpVtbl->Release(pIMalloc);
  794. return (UINT)-1;
  795. }
  796. //Clean out the existing strings.
  797. SendMessage(hList, LB_RESETCONTENT, 0, 0L);
  798. cStrings=0;
  799. while (TRUE)
  800. {
  801. lRet=RegEnumKey(hKey, cStrings++, pszClass, OLEUI_CCHKEYMAX_SIZE);
  802. if ((LONG)ERROR_SUCCESS!=lRet)
  803. break;
  804. //Cheat on lstrcat by using lstrcpy after this string, saving time
  805. cch=lstrlen(pszClass);
  806. // Check for \NotInsertable. if this is found then this overrides
  807. // all other keys; this class will NOT be added to the InsertObject
  808. // list.
  809. lstrcpy(pszClass+cch, TEXT("\\NotInsertable"));
  810. dw=OLEUI_CCHKEYMAX_SIZE;
  811. lRet=RegQueryValue(hKey, pszClass, pszKey, &dw);
  812. if ((LONG)ERROR_SUCCESS==lRet)
  813. continue; // NotInsertable IS found--skip this class
  814. //Check for a \protocol\StdFileEditing\server entry.
  815. lstrcpy(pszClass+cch, TEXT("\\protocol\\StdFileEditing\\server"));
  816. dw=OLEUI_CCHKEYMAX_SIZE;
  817. lRet=RegQueryValue(hKey, pszClass, pszKey, &dw);
  818. if ((LONG)ERROR_SUCCESS==lRet)
  819. {
  820. /*
  821. * Check if the EXE actually exists. By default we don't do this
  822. * to bring up the dialog faster. If an application wants to be
  823. * stringent, they can provide IOF_VERIFYSERVERSEXIST.
  824. */
  825. hFile = !HFILE_ERROR;
  826. if (fVerify)
  827. hFile=DoesFileExist(pszKey, &of);
  828. if (HFILE_ERROR!=hFile)
  829. {
  830. dw=OLEUI_CCHKEYMAX_SIZE;
  831. *(pszClass+cch)=0; // set back to rootkey
  832. // Get full user type name
  833. lRet=RegQueryValue(hKey, pszClass, pszKey, &dw);
  834. if ((LONG)ERROR_SUCCESS!=lRet)
  835. continue; // error getting type name--skip this class
  836. //Tell the code below to get the string for us.
  837. pszID=NULL;
  838. }
  839. }
  840. else
  841. {
  842. /*
  843. * No \protocol\StdFileEditing\server entry. Look to see if
  844. * there's an Insertable entry. If there is, then use the
  845. * Clsid to look at CLSID\clsid\LocalServer and \InprocServer
  846. */
  847. lstrcpy(pszClass+cch, TEXT("\\Insertable"));
  848. dw=OLEUI_CCHKEYMAX_SIZE;
  849. lRet=RegQueryValue(hKey, pszClass, pszKey, &dw);
  850. if ((LONG)ERROR_SUCCESS!=lRet)
  851. continue; // Insertable NOT found--skip this class
  852. //Get memory for pszID
  853. pszID=pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHKEYMAX_SIZE);
  854. if (NULL==pszID)
  855. continue;
  856. *(pszClass+cch)=0; // set back to rootkey
  857. lstrcat(pszClass+cch, TEXT("\\CLSID"));
  858. dw=OLEUI_CCHKEYMAX_SIZE;
  859. lRet=RegQueryValue(hKey, pszClass, pszID, &dw);
  860. if ((LONG)ERROR_SUCCESS!=lRet)
  861. continue; // CLSID subkey not found
  862. lstrcpy(pszExec, TEXT("CLSID\\"));
  863. lstrcat(pszExec, pszID);
  864. //CLSID\ is 6, dw contains pszID length.
  865. cch=6+(UINT)dw;
  866. lstrcpy(pszExec+cch, TEXT("\\LocalServer"));
  867. dw=OLEUI_CCHKEYMAX_SIZE;
  868. lRet=RegQueryValue(hKey, pszExec, pszKey, &dw);
  869. if ((LONG)ERROR_SUCCESS!=lRet)
  870. {
  871. //Try InprocServer
  872. lstrcpy(pszExec+cch, TEXT("\\InProcServer"));
  873. dw=OLEUI_CCHKEYMAX_SIZE;
  874. lRet=RegQueryValue(hKey, pszExec, pszKey, &dw);
  875. if ((LONG)ERROR_SUCCESS!=lRet)
  876. continue;
  877. }
  878. if (fVerify)
  879. {
  880. if (HFILE_ERROR==DoesFileExist(pszKey, &of))
  881. continue;
  882. }
  883. dw=OLEUI_CCHKEYMAX_SIZE;
  884. lRet=RegQueryValue(hKey, pszExec, pszKey, &dw);
  885. *(pszExec+cch)=0; //Remove \\*Server
  886. if ((LONG)ERROR_SUCCESS!=lRet)
  887. continue;
  888. }
  889. //Get CLSID to add to listbox.
  890. if (NULL==pszID)
  891. {
  892. CLSIDFromProgIDA(pszClass, &clsid);
  893. StringFromCLSIDA(&clsid, &pszID);
  894. }
  895. else
  896. CLSIDFromStringA(pszID, &clsid);
  897. //Check if this CLSID is in the exclusion list.
  898. fExclude=FALSE;
  899. for (i=0; i < cIDEx; i++)
  900. {
  901. if (IsEqualCLSID(&clsid, (LPCLSID)(lpIDEx+i)))
  902. {
  903. fExclude=TRUE;
  904. break;
  905. }
  906. }
  907. if (fExclude)
  908. continue;
  909. //We go through all the conditions, add the string.
  910. lstrcat(pszKey, TEXT("\t"));
  911. // only add to listbox if not a duplicate
  912. if (LB_ERR==SendMessage(hList,LB_FINDSTRING,0,(LPARAM)pszKey)) {
  913. lstrcat(pszKey, pszID);
  914. SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)pszKey);
  915. }
  916. //We always allocated this regardless of the path
  917. pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszID);
  918. }
  919. //Select the first item by default
  920. SendMessage(hList, LB_SETCURSEL, 0, 0L);
  921. RegCloseKey(hKey);
  922. pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszExec);
  923. pIMalloc->lpVtbl->Release(pIMalloc);
  924. return cStrings;
  925. }
  926. /*
  927. * FToggleObjectSource
  928. *
  929. * Purpose:
  930. * Handles enabling, disabling, showing, and flag manipulation when the
  931. * user changes between Create New, Insert File, and Link File in the
  932. * Insert Object dialog.
  933. *
  934. * Parameters:
  935. * hDlg HWND of the dialog
  936. * lpIO LPINSERTOBJECT pointing to the dialog structure
  937. * dwOption DWORD flag indicating the option just selected:
  938. * IOF_SELECTCREATENEW or IOF_SELECTCREATEFROMFILE
  939. *
  940. * Return Value:
  941. * BOOL TRUE if the option was already selected, FALSE otherwise.
  942. */
  943. BOOL FToggleObjectSource(HWND hDlg, LPINSERTOBJECT lpIO, DWORD dwOption)
  944. {
  945. BOOL fTemp;
  946. UINT uTemp;
  947. DWORD dwTemp;
  948. int i;
  949. //Skip all of this if we're already selected.
  950. if (lpIO->dwFlags & dwOption)
  951. return TRUE;
  952. // if we're switching from "from file" to "create new" and we've got
  953. // an icon for "from file", then we need to save it so that we can
  954. // show it if the user reselects "from file".
  955. if ( (IOF_SELECTCREATENEW == dwOption) &&
  956. (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) )
  957. lpIO->hMetaPictFile = (HGLOBAL)SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  958. /*
  959. * 1. Change the Display As Icon checked state to reflect the
  960. * selection for this option, stored in the fAsIcon* flags.
  961. */
  962. fTemp=(IOF_SELECTCREATENEW==dwOption) ? lpIO->fAsIconNew : lpIO->fAsIconFile;
  963. if (fTemp)
  964. lpIO->dwFlags |=IOF_CHECKDISPLAYASICON;
  965. else
  966. lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
  967. CheckDlgButton(hDlg, ID_IO_DISPLAYASICON
  968. , (BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)));
  969. EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), fTemp);
  970. /*
  971. * 2. Display Icon: Enabled on Create New or on Create from File if
  972. * there is a selected file.
  973. */
  974. fTemp=(IOF_SELECTCREATENEW==dwOption) ? TRUE : lpIO->fFileSelected;
  975. EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), fTemp);
  976. //OK and Link follow the same enabling as Display As Icon.
  977. EnableWindow(GetDlgItem(hDlg, IDOK), fTemp);
  978. EnableWindow(GetDlgItem(hDlg, ID_IO_LINKFILE), fTemp);
  979. //3. Enable Browse... when Create from File is selected.
  980. fTemp=(IOF_SELECTCREATENEW==dwOption);
  981. EnableWindow(GetDlgItem(hDlg, ID_IO_FILE), !fTemp);
  982. EnableWindow(GetDlgItem(hDlg, ID_IO_FILEDISPLAY), !fTemp);
  983. /*
  984. * 4. Switch between Object Type listbox on Create New and
  985. * file buttons on others.
  986. */
  987. uTemp=(fTemp) ? SW_SHOWNORMAL : SW_HIDE;
  988. StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPELIST, uTemp);
  989. StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPETEXT, uTemp);
  990. uTemp=(fTemp) ? SW_HIDE : SW_SHOWNORMAL;
  991. StandardShowDlgItem(hDlg, ID_IO_FILETEXT, uTemp);
  992. StandardShowDlgItem(hDlg, ID_IO_FILETYPE, uTemp);
  993. StandardShowDlgItem(hDlg, ID_IO_FILEDISPLAY, uTemp);
  994. StandardShowDlgItem(hDlg, ID_IO_FILE, uTemp);
  995. //Link is always hidden if IOF_DISABLELINK is set.
  996. if (IOF_DISABLELINK & lpIO->dwFlags)
  997. uTemp=SW_HIDE;
  998. StandardShowDlgItem(hDlg, ID_IO_LINKFILE, uTemp); //last use of uTemp
  999. //5. Clear out existing any flags selection and set the new one
  1000. dwTemp=IOF_SELECTCREATENEW | IOF_SELECTCREATEFROMFILE;
  1001. lpIO->dwFlags=(lpIO->dwFlags & ~dwTemp) | dwOption;
  1002. /*
  1003. * Show or hide controls as appropriate. Do the icon
  1004. * display last because it will take some time to repaint.
  1005. * If we do it first then the dialog looks too sluggish.
  1006. */
  1007. i=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON) ? SW_SHOWNORMAL : SW_HIDE;
  1008. StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, i);
  1009. StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, i);
  1010. //6.Change result display
  1011. SetInsertObjectResults(hDlg, lpIO);
  1012. /*
  1013. * 7. For Create New, twiddle the listbox to think we selected it
  1014. * so it updates the icon from the object type. set the focus
  1015. * to the list box.
  1016. *
  1017. * For Insert or Link file, set the focus to the filename button
  1018. * and update the icon if necessary.
  1019. */
  1020. if (fTemp) {
  1021. UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
  1022. SetFocus(GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
  1023. }
  1024. else
  1025. {
  1026. if (lpIO->fAsIconFile && (NULL != lpIO->hMetaPictFile) )
  1027. {
  1028. SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)lpIO->hMetaPictFile, 0L);
  1029. lpIO->hMetaPictFile = 0;
  1030. }
  1031. else
  1032. UpdateClassIcon(hDlg, lpIO, NULL);
  1033. SetFocus(GetDlgItem(hDlg, ID_IO_FILE));
  1034. }
  1035. return FALSE;
  1036. }
  1037. /*
  1038. * UpdateClassType
  1039. *
  1040. * Purpose:
  1041. * Updates static text control to reflect current file type. Assumes
  1042. * a valid filename.
  1043. *
  1044. * Parameters
  1045. * hDlg HWND of the dialog box.
  1046. * lpIO LPINSERTOBJECT pointing to the dialog structure
  1047. * fSet TRUE to set the text, FALSE to explicitly clear it
  1048. *
  1049. * Return Value:
  1050. * None
  1051. */
  1052. void UpdateClassType(HWND hDlg, LPINSERTOBJECT lpIO, BOOL fSet)
  1053. {
  1054. CLSID clsid;
  1055. TCHAR szFileName[OLEUI_CCHPATHMAX];
  1056. TCHAR szFileType[OLEUI_CCHLABELMAX];
  1057. *szFileType = TEXT('\0');
  1058. if (fSet)
  1059. {
  1060. GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szFileName, OLEUI_CCHPATHMAX);
  1061. if (NOERROR == GetClassFileA(szFileName, &clsid) )
  1062. OleStdGetUserTypeOfClass(&clsid, szFileType, OLEUI_CCHLABELMAX_SIZE, NULL);
  1063. }
  1064. SetDlgItemText(hDlg, ID_IO_FILETYPE, (LPTSTR)szFileType);
  1065. return;
  1066. }
  1067. /*
  1068. * UpdateClassIcon
  1069. *
  1070. * Purpose:
  1071. * Handles LBN_SELCHANGE for the Object Type listbox. On a selection
  1072. * change, we extract an icon from the server handling the currently
  1073. * selected object type using the utility function HIconFromClass.
  1074. * Note that we depend on the behavior of FillClassList to stuff the
  1075. * object class after a tab in the listbox string that we hide from
  1076. * view (see WM_INITDIALOG).
  1077. *
  1078. * Parameters
  1079. * hDlg HWND of the dialog box.
  1080. * lpIO LPINSERTOBJECT pointing to the dialog structure
  1081. * hList HWND of the Object Type listbox.
  1082. *
  1083. * Return Value:
  1084. * None
  1085. */
  1086. void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList)
  1087. {
  1088. UINT iSel;
  1089. DWORD cb;
  1090. LPMALLOC pIMalloc;
  1091. LPTSTR pszName, pszCLSID, pszTemp;
  1092. HGLOBAL hMetaPict;
  1093. LRESULT dwRet;
  1094. //If Display as Icon is not selected, exit
  1095. if (!(lpIO->dwFlags & IOF_CHECKDISPLAYASICON))
  1096. return;
  1097. /*
  1098. * When we change object type selection, get the new icon for that
  1099. * type into our structure and update it in the display. We use the
  1100. * class in the listbox when Create New is selected or the association
  1101. * with the extension in Create From File.
  1102. */
  1103. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  1104. {
  1105. iSel=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  1106. if (LB_ERR==(int)iSel)
  1107. return;
  1108. //Check to see if we've already got the hMetaPict for this item
  1109. dwRet=SendMessage(hList, LB_GETITEMDATA, (WPARAM)iSel, 0L);
  1110. hMetaPict=(HGLOBAL)(UINT)dwRet;
  1111. if (hMetaPict)
  1112. {
  1113. //Yep, we've already got it, so just display it and return.
  1114. SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)hMetaPict, 0L);
  1115. return;
  1116. }
  1117. iSel=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  1118. if (LB_ERR==(int)iSel)
  1119. return;
  1120. //Allocate a string to hold the entire listbox string
  1121. cb=SendMessage(hList, LB_GETTEXTLEN, iSel, 0L);
  1122. }
  1123. else
  1124. cb=OLEUI_CCHPATHMAX_SIZE;
  1125. if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc))
  1126. return;
  1127. pszName=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, cb+1*sizeof(TCHAR) );
  1128. if (NULL==pszName)
  1129. {
  1130. pIMalloc->lpVtbl->Release(pIMalloc);
  1131. return;
  1132. }
  1133. *pszName=0;
  1134. //Get the clsid we want.
  1135. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  1136. {
  1137. //Grab the classname string from the list
  1138. SendMessage(hList, LB_GETTEXT, iSel, (LONG)pszName);
  1139. //Set pointer to CLSID (string)
  1140. pszCLSID=PointerToNthField(pszName, 2, TEXT('\t'));
  1141. //Null terminate pszName string
  1142. #ifdef WIN32
  1143. // AnsiPrev is obsolete in Win32
  1144. pszTemp=CharPrev((LPCTSTR) pszName,(LPCTSTR) pszCLSID);
  1145. #else
  1146. pszTemp=AnsiPrev((LPCTSTR) pszName,(LPCTSTR) pszCLSID);
  1147. #endif
  1148. *pszTemp=TEXT('\0');
  1149. CLSIDFromStringA(pszCLSID, &lpIO->clsid);
  1150. #ifdef OLE201
  1151. hMetaPict = GetIconOfClass(ghInst, &lpIO->clsid, NULL, TRUE);
  1152. #endif
  1153. }
  1154. else
  1155. {
  1156. //Get the class from the filename
  1157. GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, pszName, OLEUI_CCHPATHMAX);
  1158. #ifdef OLE201
  1159. hMetaPict = OleGetIconOfFileA(pszName,
  1160. lpIO->dwFlags & IOF_CHECKLINK ? TRUE : FALSE);
  1161. #endif
  1162. }
  1163. //Replace the current display with this new one.
  1164. SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)hMetaPict, 0L);
  1165. //Enable or disable "Change Icon" button depending on whether
  1166. //we've got a valid filename or not.
  1167. EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), hMetaPict ? TRUE : FALSE);
  1168. //Save the hMetaPict so that we won't have to re-create
  1169. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  1170. SendMessage(hList, LB_SETITEMDATA, (WPARAM)iSel, hMetaPict);
  1171. pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszName);
  1172. pIMalloc->lpVtbl->Release(pIMalloc);
  1173. return;
  1174. }
  1175. /*
  1176. * SetInsertObjectResults
  1177. *
  1178. * Purpose:
  1179. * Centralizes setting of the Result and icon displays in the Insert Object
  1180. * dialog. Handles loading the appropriate string from the module's
  1181. * resources and setting the text, displaying the proper result picture,
  1182. * and showing the proper icon.
  1183. *
  1184. * Parameters:
  1185. * hDlg HWND of the dialog box so we can access controls.
  1186. * lpIO LPINSERTOBJECT in which we assume that the
  1187. * current radiobutton and Display as Icon selections
  1188. * are set. We use the state of those variables to
  1189. * determine which string we use.
  1190. *
  1191. * Return Value:
  1192. * None
  1193. */
  1194. void SetInsertObjectResults(HWND hDlg, LPINSERTOBJECT lpIO)
  1195. {
  1196. LPTSTR pszT, psz1, psz2, psz3, psz4, pszTemp;
  1197. UINT i, iString1, iString2, iImage, cch;
  1198. LPMALLOC pIMalloc;
  1199. BOOL fAsIcon;
  1200. /*
  1201. * We need scratch memory for loading the stringtable string, loading
  1202. * the object type from the listbox, and constructing the final string.
  1203. * We therefore allocate three buffers as large as the maximum message
  1204. * length (512) plus the object type, guaranteeing that we have enough
  1205. * in all cases.
  1206. */
  1207. i=(UINT)SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETCURSEL, 0, 0L);
  1208. cch=512+
  1209. (UINT)SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETTEXTLEN, i, 0L);
  1210. if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc))
  1211. return;
  1212. pszTemp=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, (DWORD)(4*cch*sizeof(TCHAR)));
  1213. if (NULL==pszTemp)
  1214. {
  1215. pIMalloc->lpVtbl->Release(pIMalloc);
  1216. return;
  1217. }
  1218. psz1=pszTemp;
  1219. psz2=psz1+cch;
  1220. psz3=psz2+cch;
  1221. psz4=psz3+cch;
  1222. fAsIcon=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON));
  1223. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  1224. {
  1225. iString1 = fAsIcon ? IDS_IORESULTNEWICON : IDS_IORESULTNEW;
  1226. iString2 = 0;
  1227. iImage = fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
  1228. }
  1229. if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
  1230. {
  1231. //Pay attention to Link checkbox
  1232. if (lpIO->dwFlags & IOF_CHECKLINK)
  1233. {
  1234. iString1 = fAsIcon ? IDS_IORESULTLINKFILEICON1 : IDS_IORESULTLINKFILE1;
  1235. iString2 = fAsIcon ? IDS_IORESULTLINKFILEICON2 : IDS_IORESULTLINKFILE2;
  1236. iImage =fAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK;
  1237. }
  1238. else
  1239. {
  1240. iString1 = IDS_IORESULTFROMFILE1;
  1241. iString2 = fAsIcon ? IDS_IORESULTFROMFILEICON2 : IDS_IORESULTFROMFILE2;
  1242. iImage =fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
  1243. }
  1244. }
  1245. //Default is an empty string.
  1246. *psz1=0;
  1247. if (0!=LoadString(ghInst, iString1, psz1, cch))
  1248. {
  1249. // Load second string, if necessary
  1250. if ( (0 != iString2)
  1251. && (0 != LoadString(ghInst, iString2, psz4, cch)) )
  1252. {
  1253. lstrcat(psz1, psz4); // concatenate strings together.
  1254. }
  1255. //In Create New, do the extra step of inserting the object type string
  1256. if (lpIO->dwFlags & IOF_SELECTCREATENEW)
  1257. {
  1258. SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETTEXT
  1259. , i, (LONG)psz2);
  1260. //Null terminate at any tab (before the classname)
  1261. pszT=psz2;
  1262. while (TEXT('\t')!=*pszT && 0!=*pszT)
  1263. pszT++;
  1264. *pszT=0;
  1265. //Build the string and point psz1 to it.
  1266. wsprintf(psz3, psz1, psz2);
  1267. psz1=psz3;
  1268. }
  1269. }
  1270. //If LoadString failed, we simply clear out the results (*psz1=0 above)
  1271. SetDlgItemText(hDlg, ID_IO_RESULTTEXT, psz1);
  1272. //Go change the image and Presto! There you have it.
  1273. SendDlgItemMessage(hDlg, ID_IO_RESULTIMAGE, RIM_IMAGESET, iImage, 0L);
  1274. pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszTemp);
  1275. pIMalloc->lpVtbl->Release(pIMalloc);
  1276. return;
  1277. }
  1278. /*
  1279. * FValidateInsertFile
  1280. *
  1281. * Purpose:
  1282. * Given a possibly partial pathname from the file edit control,
  1283. * attempt to locate the file and if found, store the full path
  1284. * in the edit control ID_IO_FILEDISPLAY.
  1285. *
  1286. * Parameters:
  1287. * hDlg HWND of the dialog box.
  1288. * fTellUser BOOL TRUE if function should tell user, FALSE if
  1289. * function should validate silently.
  1290. *
  1291. * Return Value:
  1292. * BOOL TRUE if the file is acceptable, FALSE otherwise.
  1293. */
  1294. BOOL FValidateInsertFile(HWND hDlg, BOOL fTellUser, UINT FAR* lpnErrCode)
  1295. {
  1296. OFSTRUCT of;
  1297. HFILE hFile;
  1298. TCHAR szFile[OLEUI_CCHPATHMAX];
  1299. *lpnErrCode = 0;
  1300. /*
  1301. * To validate we attempt OpenFile on the string. If OpenFile
  1302. * fails then we display an error. If not, OpenFile will store
  1303. * the complete path to that file in the OFSTRUCT which we can
  1304. * then stuff in the edit control.
  1305. */
  1306. if (0==GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, szFile, OLEUI_CCHPATHMAX))
  1307. return FALSE; // #4569 : return FALSE when there is no text in ctl
  1308. hFile=DoesFileExist(szFile, &of);
  1309. // if file is currently open (ie. sharing violation) OleCreateFromFile
  1310. // and OleCreateLinkToFile can still succeed; do not consider it an
  1311. // error.
  1312. if (HFILE_ERROR==hFile && 0x0020/*sharing violation*/!=of.nErrCode)
  1313. {
  1314. *lpnErrCode = of.nErrCode;
  1315. if (fTellUser)
  1316. OpenFileError(hDlg, of.nErrCode, szFile);
  1317. return FALSE;
  1318. }
  1319. //OFSTRUCT contains an OEM name, not ANSI as we need for the edit box.
  1320. OemToAnsi(of.szPathName, of.szPathName);
  1321. SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, of.szPathName);
  1322. return TRUE;
  1323. }
  1324. /*
  1325. * InsertObjectCleanup
  1326. *
  1327. * Purpose:
  1328. * Clears cached icon metafiles from those stored in the listbox.
  1329. *
  1330. * Parameters:
  1331. * hDlg HWND of the dialog.
  1332. *
  1333. * Return Value:
  1334. * None
  1335. */
  1336. void InsertObjectCleanup(HWND hDlg)
  1337. {
  1338. HWND hList;
  1339. UINT iItems;
  1340. HGLOBAL hMetaPict;
  1341. LRESULT dwRet;
  1342. UINT i;
  1343. hList=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST);
  1344. iItems=(UINT)SendMessage(hList, LB_GETCOUNT, 0, 0L);
  1345. for (i=0; i < iItems; i++)
  1346. {
  1347. dwRet=SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
  1348. //Cast of LRESULT to UINT to HGLOBAL portable to Win32.
  1349. hMetaPict=(HGLOBAL)(UINT)dwRet;
  1350. if (hMetaPict)
  1351. OleUIMetafilePictIconFree(hMetaPict);
  1352. }
  1353. return;
  1354. }