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.

441 lines
15 KiB

  1. /*
  2. * CHNGSRC.CPP
  3. *
  4. * Implements the OleUIChangeSource function which invokes the complete
  5. * Change Source dialog.
  6. *
  7. * Copyright (c)1992 Microsoft Corporation, All Right Reserved
  8. */
  9. #include "precomp.h"
  10. #include "common.h"
  11. #include "utility.h"
  12. #include "strsafe.h"
  13. OLEDBGDATA
  14. // Internally used structure
  15. typedef struct tagCHANGESOURCE
  16. {
  17. // Keep this item first as the Standard* functions depend on it here.
  18. LPOLEUICHANGESOURCE lpOCS; //Original structure passed.
  19. UINT nIDD; // IDD of dialog (used for help info)
  20. /*
  21. * What we store extra in this structure besides the original caller's
  22. * pointer are those fields that we need to modify during the life of
  23. * the dialog but that we don't want to change in the original structure
  24. * until the user presses OK.
  25. */
  26. } CHANGESOURCE, *PCHANGESOURCE, FAR* LPCHANGESOURCE;
  27. // Internal function prototypes
  28. // CHNGSRC.CPP
  29. UINT_PTR CALLBACK ChangeSourceHookProc(HWND, UINT, WPARAM, LPARAM);
  30. BOOL FChangeSourceInit(HWND hDlg, WPARAM, LPARAM);
  31. STDAPI_(BOOL) IsValidInterface(void FAR* ppv);
  32. /*
  33. * OleUIChangeSource
  34. *
  35. * Purpose:
  36. * Invokes the standard OLE Change Source dialog box allowing the user
  37. * to change the source of a link. The link source is not actually
  38. * changed by this dialog. It is up to the caller to actually change
  39. * the link source itself.
  40. *
  41. * Parameters:
  42. * lpCS LPOLEUIChangeSource pointing to the in-out structure
  43. * for this dialog.
  44. *
  45. * Return Value:
  46. * UINT One of the following codes, indicating success or error:
  47. * OLEUI_SUCCESS Success
  48. * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong
  49. */
  50. STDAPI_(UINT) OleUIChangeSource(LPOLEUICHANGESOURCE lpCS)
  51. {
  52. HGLOBAL hMemDlg = NULL;
  53. UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpCS,
  54. sizeof(OLEUICHANGESOURCE), &hMemDlg);
  55. if (OLEUI_SUCCESS != uRet)
  56. return uRet;
  57. HCURSOR hCurSave = NULL;
  58. // validate contents of lpCS
  59. if (lpCS->lpOleUILinkContainer == NULL)
  60. {
  61. uRet = OLEUI_CSERR_LINKCNTRNULL;
  62. goto Error;
  63. }
  64. if (!IsValidInterface(lpCS->lpOleUILinkContainer))
  65. {
  66. uRet = OLEUI_CSERR_LINKCNTRINVALID;
  67. goto Error;
  68. }
  69. // lpszFrom and lpszTo must be NULL (they are out only)
  70. if (lpCS->lpszFrom != NULL)
  71. {
  72. uRet = OLEUI_CSERR_FROMNOTNULL;
  73. goto Error;
  74. }
  75. if (lpCS->lpszTo != NULL)
  76. {
  77. uRet = OLEUI_CSERR_TONOTNULL;
  78. goto Error;
  79. }
  80. // lpszDisplayName must be valid or NULL
  81. if (lpCS->lpszDisplayName != NULL &&
  82. IsBadStringPtr(lpCS->lpszDisplayName, (UINT)-1))
  83. {
  84. uRet = OLEUI_CSERR_SOURCEINVALID;
  85. goto Error;
  86. }
  87. hCurSave = HourGlassOn();
  88. // attempt to retrieve link source if not provided
  89. if (lpCS->lpszDisplayName == NULL)
  90. {
  91. if (NOERROR != lpCS->lpOleUILinkContainer->GetLinkSource(
  92. lpCS->dwLink, &lpCS->lpszDisplayName, &lpCS->nFileLength,
  93. NULL, NULL, NULL, NULL))
  94. {
  95. uRet = OLEUI_CSERR_SOURCEINVALID;
  96. goto Error;
  97. }
  98. }
  99. // verify that nFileLength is valid
  100. UINT cchDisplayName = lstrlen(lpCS->lpszDisplayName);
  101. if (cchDisplayName < lpCS->nFileLength)
  102. {
  103. uRet = OLEUI_CSERR_SOURCEINVALID;
  104. goto Error;
  105. }
  106. // allocate file buffer and split directory and file name
  107. UINT nFileLength; nFileLength = lpCS->nFileLength;
  108. UINT nFileBuf; nFileBuf = max(nFileLength+1, MAX_PATH);
  109. LPTSTR lpszFileBuf;
  110. if (cchDisplayName > nFileBuf -1)
  111. {
  112. uRet = OLEUI_CSERR_SOURCEINVALID;
  113. goto Error;
  114. }
  115. LPTSTR lpszDirBuf; lpszDirBuf = (LPTSTR)OleStdMalloc(nFileBuf * sizeof(TCHAR));
  116. if (lpszDirBuf == NULL)
  117. {
  118. uRet = OLEUI_ERR_OLEMEMALLOC;
  119. goto Error;
  120. }
  121. lstrcpyn(lpszDirBuf, lpCS->lpszDisplayName, nFileLength+1);
  122. UINT nFileLen; nFileLen = GetFileName(lpszDirBuf, NULL, 0);
  123. lpszFileBuf = (LPTSTR)OleStdMalloc(nFileBuf * sizeof(TCHAR));
  124. if (lpszFileBuf == NULL)
  125. {
  126. uRet = OLEUI_ERR_OLEMEMALLOC;
  127. goto ErrorFreeDirBuf;
  128. }
  129. memmove(lpszFileBuf, lpszDirBuf+nFileLength-nFileLen+1,
  130. (nFileLen+1)*sizeof(TCHAR));
  131. lpszDirBuf[nFileLength-(nFileLen - 1)] = 0;
  132. // start filling the OPENFILENAME struct
  133. OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn));
  134. ofn.lpstrFile = lpszFileBuf;
  135. ofn.nMaxFile = nFileBuf;
  136. ofn.lpstrInitialDir = lpszDirBuf;
  137. // load filter strings
  138. TCHAR szFilters[MAX_PATH];
  139. if (!LoadString(_g_hOleStdResInst, IDS_FILTERS, szFilters, MAX_PATH))
  140. szFilters[0] = 0;
  141. else
  142. ReplaceCharWithNull(szFilters, szFilters[lstrlen(szFilters)-1]);
  143. ofn.lpstrFilter = szFilters;
  144. ofn.nFilterIndex = 1;
  145. TCHAR szTitle[MAX_PATH];
  146. // set the caption
  147. if (NULL!=lpCS->lpszCaption)
  148. ofn.lpstrTitle = lpCS->lpszCaption;
  149. else
  150. {
  151. LoadString(_g_hOleStdResInst, IDS_CHANGESOURCE, szTitle, MAX_PATH);
  152. ofn.lpstrTitle = szTitle;
  153. }
  154. // fill in rest of OPENFILENAME struct
  155. ofn.hwndOwner = lpCS->hWndOwner;
  156. ofn.lStructSize = sizeof(ofn);
  157. ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLEHOOK;
  158. if (bWin4 && ((NULL == lpCS->hInstance && NULL == lpCS->hResource)
  159. || 0 != (lpCS->dwFlags & CSF_EXPLORER)))
  160. ofn.Flags |= OFN_EXPLORER;
  161. if (lpCS->dwFlags & CSF_SHOWHELP)
  162. ofn.Flags |= OFN_SHOWHELP;
  163. ofn.lCustData = (LPARAM)lpCS;
  164. ofn.lpfnHook = ChangeSourceHookProc;
  165. ofn.lCustData = (LPARAM)lpCS;
  166. lpCS->lpOFN = &ofn; // needed sometimes in hook proc
  167. // allow hooking of the dialog resource
  168. if (lpCS->hResource != NULL)
  169. {
  170. ofn.hInstance = (HINSTANCE)lpCS->hResource;
  171. ofn.lpTemplateName = (LPCTSTR)lpCS->hResource;
  172. ofn.Flags |= OFN_ENABLETEMPLATEHANDLE;
  173. }
  174. else
  175. {
  176. if (lpCS->hInstance == NULL)
  177. {
  178. ofn.hInstance = _g_hOleStdResInst;
  179. ofn.lpTemplateName = bWin4 ?
  180. MAKEINTRESOURCE(IDD_CHANGESOURCE4) : MAKEINTRESOURCE(IDD_CHANGESOURCE);
  181. ofn.Flags |= OFN_ENABLETEMPLATE;
  182. }
  183. else
  184. {
  185. ofn.hInstance = lpCS->hInstance;
  186. ofn.lpTemplateName = lpCS->lpszTemplate;
  187. ofn.Flags |= OFN_ENABLETEMPLATE;
  188. }
  189. }
  190. if (lpCS->hWndOwner != NULL)
  191. {
  192. // allow hooking of the OFN struct
  193. SendMessage(lpCS->hWndOwner, uMsgBrowseOFN, ID_BROWSE_CHANGESOURCE, (LPARAM)&ofn);
  194. }
  195. // call up the dialog
  196. BOOL bResult;
  197. bResult = StandardGetOpenFileName(&ofn);
  198. // cleanup
  199. OleStdFree(lpszDirBuf);
  200. OleStdFree(lpszFileBuf);
  201. HourGlassOff(hCurSave);
  202. // map return value to OLEUI_ standard returns
  203. return bResult ? OLEUI_OK : OLEUI_CANCEL;
  204. // handle most error returns here
  205. ErrorFreeDirBuf:
  206. OleStdFree(lpszDirBuf);
  207. Error:
  208. if (hCurSave != NULL)
  209. HourGlassOff(hCurSave);
  210. return uRet;
  211. }
  212. /*
  213. * ChangeSourceHookProc
  214. *
  215. * Purpose:
  216. * Implements the OLE Change Source dialog as invoked through the
  217. * OleUIChangeSource function. This is a standard COMMDLG hook function
  218. * as opposed to a dialog proc.
  219. *
  220. * Parameters:
  221. * Standard
  222. *
  223. * Return Value:
  224. * Standard
  225. */
  226. UINT_PTR CALLBACK ChangeSourceHookProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  227. {
  228. // Declare Win16/Win32 compatible WM_COMMAND parameters.
  229. COMMANDPARAMS(wID, wCode, hWndMsg);
  230. // This will fail under WM_INITDIALOG, where we allocate it.
  231. UINT uHook = 0;
  232. LPCHANGESOURCE lpCS = (LPCHANGESOURCE)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook);
  233. LPOLEUICHANGESOURCE lpOCS = NULL;
  234. if (lpCS != NULL)
  235. lpOCS = lpCS->lpOCS;
  236. // If the hook processed the message, we're done.
  237. if (0 != uHook)
  238. return uHook;
  239. // Process help message
  240. if ((iMsg == uMsgHelp) && NULL != lpOCS)
  241. {
  242. PostMessage(lpOCS->hWndOwner, uMsgHelp,
  243. (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0));
  244. }
  245. // Process the temination message
  246. if (iMsg == uMsgEndDialog)
  247. {
  248. // Free any specific allocations before calling StandardCleanup
  249. StandardCleanup((PVOID)lpCS, hDlg);
  250. EndDialog(hDlg, wParam);
  251. return TRUE;
  252. }
  253. // handle validation of the file name (when user hits OK)
  254. if ((iMsg == uMsgFileOKString) && (lpOCS != NULL))
  255. {
  256. // always use fully qualified name
  257. LPOPENFILENAME lpOFN = lpOCS->lpOFN;
  258. LPCTSTR lpsz = lpOFN->lpstrFile;
  259. LPTSTR lpszFile;
  260. TCHAR szPath[MAX_PATH];
  261. if (!GetFullPathName(lpsz, MAX_PATH, szPath, &lpszFile))
  262. lstrcpyn(szPath, lpsz, MAX_PATH);
  263. UINT nLenFile = lstrlen(szPath);
  264. TCHAR szItemName[MAX_PATH];
  265. GetDlgItemText(hDlg, edt2, szItemName, MAX_PATH);
  266. // combine them into szDisplayName (which is now large enough)
  267. TCHAR szDisplayName[MAX_PATH+MAX_PATH];
  268. StringCchCopy(szDisplayName, sizeof(szDisplayName)/sizeof(szDisplayName[0]), szPath);
  269. if (szItemName[0] != '\0')
  270. {
  271. StringCchCat(szDisplayName, sizeof(szDisplayName)/sizeof(szDisplayName[0]), TEXT("\\"));
  272. StringCchCat(szDisplayName, sizeof(szDisplayName)/sizeof(szDisplayName[0]), szItemName);
  273. }
  274. if (!(lpOCS->dwFlags & CSF_ONLYGETSOURCE))
  275. {
  276. // verify the source by calling into the link container
  277. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpOCS->lpOleUILinkContainer;
  278. ULONG chEaten;
  279. if (lpOleUILinkCntr->SetLinkSource(lpOCS->dwLink, szDisplayName, nLenFile,
  280. &chEaten, TRUE) != NOERROR)
  281. {
  282. // link not verified ok
  283. lpOCS->dwFlags &= ~CSF_VALIDSOURCE;
  284. UINT uRet = PopupMessage(hDlg, IDS_CHANGESOURCE, IDS_INVALIDSOURCE,
  285. MB_ICONQUESTION | MB_YESNO);
  286. if (uRet == IDYES)
  287. {
  288. SetWindowLong(hDlg, DWLP_MSGRESULT, 1);
  289. return 1; // do not close dialog
  290. }
  291. // user doesn't care if the link is valid or not
  292. lpOleUILinkCntr->SetLinkSource(lpOCS->dwLink, szDisplayName, nLenFile,
  293. &chEaten, FALSE);
  294. }
  295. else
  296. {
  297. // link was verified ok
  298. lpOCS->dwFlags |= CSF_VALIDSOURCE;
  299. }
  300. }
  301. // calculate lpszFrom and lpszTo for batch changes to links
  302. DiffPrefix(lpOCS->lpszDisplayName, szDisplayName, &lpOCS->lpszFrom, &lpOCS->lpszTo);
  303. // only keep them if the file name portion is the only part that changed
  304. if (lstrcmpi(lpOCS->lpszTo, lpOCS->lpszFrom) == 0 ||
  305. (UINT)lstrlen(lpOCS->lpszFrom) > lpOCS->nFileLength)
  306. {
  307. OleStdFree(lpOCS->lpszFrom);
  308. lpOCS->lpszFrom = NULL;
  309. OleStdFree(lpOCS->lpszTo);
  310. lpOCS->lpszTo = NULL;
  311. }
  312. // store new source in lpOCS->lpszDisplayName
  313. OleStdFree(lpOCS->lpszDisplayName);
  314. lpOCS->lpszDisplayName = OleStdCopyString(szDisplayName);
  315. lpOCS->nFileLength = nLenFile;
  316. return 0;
  317. }
  318. switch (iMsg)
  319. {
  320. case WM_NOTIFY:
  321. if (((NMHDR*)lParam)->code == CDN_HELP)
  322. {
  323. goto POSTHELP;
  324. }
  325. break;
  326. case WM_COMMAND:
  327. if (wID == pshHelp)
  328. {
  329. POSTHELP:
  330. PostMessage(lpCS->lpOCS->hWndOwner, uMsgHelp,
  331. (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0));
  332. }
  333. break;
  334. case WM_INITDIALOG:
  335. return FChangeSourceInit(hDlg, wParam, lParam);
  336. }
  337. return 0;
  338. }
  339. /*
  340. * FChangeSourceInit
  341. *
  342. * Purpose:
  343. * WM_INITIDIALOG handler for the Change Source dialog box.
  344. *
  345. * Parameters:
  346. * hDlg HWND of the dialog
  347. * wParam WPARAM of the message
  348. * lParam LPARAM of the message
  349. *
  350. * Return Value:
  351. * BOOL Value to return for WM_INITDIALOG.
  352. */
  353. BOOL FChangeSourceInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
  354. {
  355. // Copy the structure at lParam into our instance memory.
  356. LPCHANGESOURCE lpCS = (LPCHANGESOURCE)LpvStandardInit(hDlg, sizeof(CHANGESOURCE), NULL);
  357. // PvStandardInit send a termination to us already.
  358. if (NULL == lpCS)
  359. return FALSE;
  360. LPOLEUICHANGESOURCE lpOCS=
  361. (LPOLEUICHANGESOURCE)((LPOPENFILENAME)lParam)->lCustData;
  362. lpCS->lpOCS = lpOCS;
  363. lpCS->nIDD = IDD_CHANGESOURCE;
  364. // Setup Item text box with item part of lpszDisplayName
  365. LPTSTR lpszItemName = lpOCS->lpszDisplayName + lpOCS->nFileLength;
  366. if (*lpszItemName != '\0')
  367. SetDlgItemText(hDlg, edt2, lpszItemName+1);
  368. SendDlgItemMessage(hDlg, edt2, EM_LIMITTEXT, MAX_PATH, 0L);
  369. // Change the caption
  370. if (NULL!=lpOCS->lpszCaption)
  371. SetWindowText(hDlg, lpOCS->lpszCaption);
  372. // Call the hook with lCustData in lParam
  373. UStandardHook((PVOID)lpCS, hDlg, WM_INITDIALOG, wParam, lpOCS->lCustData);
  374. #ifdef CHICO
  375. TCHAR szTemp[MAX_PATH];
  376. LoadString(_g_hOleStdResInst, IDS_CHNGSRCOKBUTTON , szTemp, MAX_PATH);
  377. CommDlg_OpenSave_SetControlText(GetParent(hDlg), IDOK, szTemp);
  378. #endif
  379. return TRUE;
  380. }
  381. /////////////////////////////////////////////////////////////////////////////