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.

835 lines
26 KiB

  1. /*
  2. * UTILITY.CPP
  3. *
  4. * Utility routines for functions inside OLEDLG.DLL
  5. *
  6. * General:
  7. * ----------------------
  8. * HourGlassOn Displays the hourglass
  9. * HourGlassOff Hides the hourglass
  10. *
  11. * Misc Tools:
  12. * ----------------------
  13. * Browse Displays the "File..." or "Browse..." dialog.
  14. * ReplaceCharWithNull Used to form filter strings for Browse.
  15. * ErrorWithFile Creates an error message with embedded filename
  16. * OpenFileError Give error message for OpenFile error return
  17. * ChopText Chop a file path to fit within a specified width
  18. * DoesFileExist Checks if file is valid
  19. *
  20. *
  21. * Copyright (c)1992 Microsoft Corporation, All Right Reserved
  22. */
  23. #include "precomp.h"
  24. #include "common.h"
  25. #include <stdlib.h>
  26. #include <commdlg.h>
  27. #include <memory.h>
  28. #include <cderr.h>
  29. #include "utility.h"
  30. OLEDBGDATA
  31. /*
  32. * HourGlassOn
  33. *
  34. * Purpose:
  35. * Shows the hourglass cursor returning the last cursor in use.
  36. *
  37. * Parameters:
  38. * None
  39. *
  40. * Return Value:
  41. * HCURSOR Cursor in use prior to showing the hourglass.
  42. */
  43. HCURSOR WINAPI HourGlassOn(void)
  44. {
  45. HCURSOR hCur;
  46. hCur=SetCursor(LoadCursor(NULL, IDC_WAIT));
  47. ShowCursor(TRUE);
  48. return hCur;
  49. }
  50. /*
  51. * HourGlassOff
  52. *
  53. * Purpose:
  54. * Turns off the hourglass restoring it to a previous cursor.
  55. *
  56. * Parameters:
  57. * hCur HCURSOR as returned from HourGlassOn
  58. *
  59. * Return Value:
  60. * None
  61. */
  62. void WINAPI HourGlassOff(HCURSOR hCur)
  63. {
  64. ShowCursor(FALSE);
  65. SetCursor(hCur);
  66. return;
  67. }
  68. /*
  69. * Browse
  70. *
  71. * Purpose:
  72. * Displays the standard GetOpenFileName dialog with the title of
  73. * "Browse." The types listed in this dialog are controlled through
  74. * iFilterString. If it's zero, then the types are filled with "*.*"
  75. * Otherwise that string is loaded from resources and used.
  76. *
  77. * Parameters:
  78. * hWndOwner HWND owning the dialog
  79. * lpszFile LPSTR specifying the initial file and the buffer in
  80. * which to return the selected file. If there is no
  81. * initial file the first character of this string should
  82. * be NULL.
  83. * lpszInitialDir LPSTR specifying the initial directory. If none is to
  84. * set (ie, the cwd should be used), then this parameter
  85. * should be NULL.
  86. * cchFile UINT length of pszFile
  87. * iFilterString UINT index into the stringtable for the filter string.
  88. * dwOfnFlags DWORD flags to OR with OFN_HIDEREADONLY
  89. * nBrowseID
  90. * lpfnHook Callback Hook Proceedure. Set if OFN_ENABLE_HOOK is
  91. * in dwOfnFlags else it should be NULL.
  92. *
  93. * Return Value:
  94. * BOOL TRUE if the user selected a file and pressed OK.
  95. * FALSE otherwise, such as on pressing Cancel.
  96. */
  97. BOOL WINAPI Browse(HWND hWndOwner, LPTSTR lpszFile, LPTSTR lpszInitialDir, UINT cchFile,
  98. UINT iFilterString, DWORD dwOfnFlags, UINT nBrowseID, LPOFNHOOKPROC lpfnHook)
  99. {
  100. UINT cch;
  101. TCHAR szFilters[256];
  102. TCHAR szDlgTitle[128]; // that should be big enough
  103. if (NULL == lpszFile || 0 == cchFile)
  104. return FALSE;
  105. /*
  106. * Exact contents of the filter combobox is TBD. One idea
  107. * is to take all the extensions in the RegDB and place them in here
  108. * with the descriptive class name associate with them. This has the
  109. * extra step of finding all extensions of the same class handler and
  110. * building one extension string for all of them. Can get messy quick.
  111. * UI demo has only *.* which we do for now.
  112. */
  113. if (0 != iFilterString)
  114. {
  115. cch = LoadString(_g_hOleStdResInst, iFilterString, szFilters,
  116. sizeof(szFilters)/sizeof(TCHAR));
  117. }
  118. else
  119. {
  120. szFilters[0] = 0;
  121. cch = 1;
  122. }
  123. if (0 == cch)
  124. return FALSE;
  125. ReplaceCharWithNull(szFilters, szFilters[cch-1]);
  126. // Prior string must also be initialized, if there is one.
  127. OPENFILENAME ofn;
  128. memset(&ofn, 0, sizeof(ofn));
  129. ofn.lStructSize = sizeof(ofn);
  130. ofn.hwndOwner = hWndOwner;
  131. ofn.lpstrFile = lpszFile;
  132. ofn.nMaxFile = cchFile;
  133. ofn.lpstrFilter = szFilters;
  134. ofn.nFilterIndex = 1;
  135. ofn.lpfnHook = lpfnHook;
  136. if (LoadString(_g_hOleStdResInst, IDS_BROWSE, szDlgTitle, sizeof(szDlgTitle)/sizeof(TCHAR)))
  137. ofn.lpstrTitle = szDlgTitle;
  138. ofn.hInstance = _g_hOleStdResInst;
  139. if (NULL != lpszInitialDir)
  140. ofn.lpstrInitialDir = lpszInitialDir;
  141. ofn.Flags = OFN_HIDEREADONLY | dwOfnFlags;
  142. if (bWin4)
  143. ofn.Flags |= OFN_EXPLORER;
  144. // Lastly, parent to tweak OFN parameters
  145. if (hWndOwner != NULL)
  146. SendMessage(hWndOwner, uMsgBrowseOFN, nBrowseID, (LPARAM)&ofn);
  147. // On success, copy the chosen filename to the static display
  148. BOOL bResult = StandardGetOpenFileName((LPOPENFILENAME)&ofn);
  149. return bResult;
  150. }
  151. /*
  152. * ReplaceCharWithNull
  153. *
  154. * Purpose:
  155. * Walks a null-terminated string and replaces a given character
  156. * with a zero. Used to turn a single string for file open/save
  157. * filters into the appropriate filter string as required by the
  158. * common dialog API.
  159. *
  160. * Parameters:
  161. * psz LPTSTR to the string to process.
  162. * ch int character to replace.
  163. *
  164. * Return Value:
  165. * int Number of characters replaced. -1 if psz is NULL.
  166. */
  167. int WINAPI ReplaceCharWithNull(LPTSTR psz, int ch)
  168. {
  169. int cChanged = 0;
  170. if (psz == NULL)
  171. return -1;
  172. while ('\0' != *psz)
  173. {
  174. if (ch == *psz)
  175. {
  176. *psz++ = '\0';
  177. cChanged++;
  178. continue;
  179. }
  180. psz = CharNext(psz);
  181. }
  182. return cChanged;
  183. }
  184. /*
  185. * ErrorWithFile
  186. *
  187. * Purpose:
  188. * Displays a message box built from a stringtable string containing
  189. * one %s as a placeholder for a filename and from a string of the
  190. * filename to place there.
  191. *
  192. * Parameters:
  193. * hWnd HWND owning the message box. The caption of this
  194. * window is the caption of the message box.
  195. * hInst HINSTANCE from which to draw the idsErr string.
  196. * idsErr UINT identifier of a stringtable string containing
  197. * the error message with a %s.
  198. * lpszFile LPSTR to the filename to include in the message.
  199. * uFlags UINT flags to pass to MessageBox, like MB_OK.
  200. *
  201. * Return Value:
  202. * int Return value from MessageBox.
  203. */
  204. int WINAPI ErrorWithFile(HWND hWnd, HINSTANCE hInst, UINT idsErr,
  205. LPTSTR pszFile, UINT uFlags)
  206. {
  207. int iRet=0;
  208. HANDLE hMem;
  209. const UINT cb = (2*MAX_PATH);
  210. LPTSTR psz1, psz2, psz3;
  211. if (NULL == hInst || NULL == pszFile)
  212. return iRet;
  213. // Allocate three 2*MAX_PATH byte work buffers
  214. hMem=GlobalAlloc(GHND, (DWORD)(3*cb)*sizeof(TCHAR));
  215. if (NULL==hMem)
  216. return iRet;
  217. psz1 = (LPTSTR)GlobalLock(hMem);
  218. psz2 = psz1+cb;
  219. psz3 = psz2+cb;
  220. if (0 != LoadString(hInst, idsErr, psz1, cb))
  221. {
  222. wsprintf(psz2, psz1, pszFile);
  223. // Steal the caption of the dialog
  224. GetWindowText(hWnd, psz3, cb);
  225. iRet=MessageBox(hWnd, psz2, psz3, uFlags);
  226. }
  227. GlobalUnlock(hMem);
  228. GlobalFree(hMem);
  229. return iRet;
  230. }
  231. // returns width of line of text. this is a support routine for ChopText
  232. static LONG GetTextWSize(HDC hDC, LPTSTR lpsz)
  233. {
  234. SIZE size;
  235. if (GetTextExtentPoint(hDC, lpsz, lstrlen(lpsz), (LPSIZE)&size))
  236. return size.cx;
  237. else
  238. return 0;
  239. }
  240. LPTSTR FindChar(LPTSTR lpsz, TCHAR ch)
  241. {
  242. while (*lpsz != 0)
  243. {
  244. if (*lpsz == ch)
  245. return lpsz;
  246. lpsz = CharNext(lpsz);
  247. }
  248. return NULL;
  249. }
  250. LPTSTR FindReverseChar(LPTSTR lpsz, TCHAR ch)
  251. {
  252. LPTSTR lpszLast = NULL;
  253. while (*lpsz != 0)
  254. {
  255. if (*lpsz == ch)
  256. lpszLast = lpsz;
  257. lpsz = CharNext(lpsz);
  258. }
  259. return lpszLast;
  260. }
  261. static void WINAPI Abbreviate(HDC hdc, int nWidth, LPTSTR lpch, int nMaxChars)
  262. {
  263. /* string is too long to fit; chop it */
  264. /* set up new prefix & determine remaining space in control */
  265. LPTSTR lpszFileName = NULL;
  266. LPTSTR lpszCur = CharNext(CharNext(lpch));
  267. lpszCur = FindChar(lpszCur, TEXT('\\'));
  268. // algorithm will insert \... so allocate extra 4
  269. LPTSTR lpszNew = (LPTSTR)OleStdMalloc((lstrlen(lpch)+5) * sizeof(TCHAR));
  270. if (lpszNew == NULL)
  271. return;
  272. if (lpszCur != NULL) // at least one backslash
  273. {
  274. *lpszNew = (TCHAR)0;
  275. *lpszCur = (TCHAR)0;
  276. lstrcpy(lpszNew, lpch);
  277. *lpszCur = TEXT('\\');
  278. // lpszNew now contains c: or \\servername
  279. lstrcat(lpszNew, TEXT("\\..."));
  280. // lpszNew now contains c:\... or \\servername\...
  281. LPTSTR lpszEnd = lpszNew;
  282. while (*lpszEnd != (TCHAR)0)
  283. lpszEnd = CharNext(lpszEnd);
  284. // lpszEnd is now at the end of c:\... or \\servername\...
  285. // move down directories until it fits or no more directories
  286. while (lpszCur != NULL)
  287. {
  288. *lpszEnd = (TCHAR)0;
  289. lstrcat(lpszEnd, lpszCur);
  290. if (GetTextWSize(hdc, lpszNew) <= nWidth &&
  291. lstrlen(lpszNew) < nMaxChars)
  292. {
  293. lstrcpyn(lpch, lpszNew, nMaxChars);
  294. OleStdFree(lpszNew);
  295. return;
  296. }
  297. lpszCur = CharNext(lpszCur); // advance past backslash
  298. lpszCur = FindChar(lpszCur, TEXT('\\'));
  299. }
  300. // try just ...filename and then shortening filename
  301. lpszFileName = FindReverseChar(lpch, TEXT('\\'));
  302. }
  303. else
  304. lpszFileName = lpch;
  305. while (*lpszFileName != (TCHAR)0)
  306. {
  307. lstrcpy(lpszNew, TEXT("..."));
  308. lstrcat(lpszNew, lpszFileName);
  309. if (GetTextWSize(hdc, lpszNew) <= nWidth && lstrlen(lpszNew) < nMaxChars)
  310. {
  311. lstrcpyn(lpch, lpszNew, nMaxChars);
  312. OleStdFree(lpszNew);
  313. return;
  314. }
  315. lpszFileName = CharNext(lpszFileName);
  316. }
  317. OleStdFree(lpszNew);
  318. // not even a single character fit
  319. *lpch = (TCHAR)0;
  320. }
  321. /*
  322. * ChopText
  323. *
  324. * Purpose:
  325. * Parse a string (pathname) and convert it to be within a specified
  326. * length by chopping the least significant part
  327. *
  328. * Parameters:
  329. * hWnd window handle in which the string resides
  330. * nWidth max width of string in pixels
  331. * use width of hWnd if zero
  332. * lpch pointer to beginning of the string
  333. * nMaxChars maximum allowable number of characters (0 ignore)
  334. *
  335. * Return Value:
  336. * pointer to the modified string
  337. */
  338. LPTSTR WINAPI ChopText(HWND hWnd, int nWidth, LPTSTR lpch, int nMaxChars)
  339. {
  340. HDC hdc;
  341. HFONT hfont;
  342. HFONT hfontOld = NULL;
  343. RECT rc;
  344. if (!hWnd || !lpch)
  345. return NULL;
  346. if (nMaxChars == 0)
  347. nMaxChars = 32768; // big number
  348. /* Get length of static field. */
  349. if (!nWidth)
  350. {
  351. GetClientRect(hWnd, (LPRECT)&rc);
  352. nWidth = rc.right - rc.left;
  353. }
  354. /* Set up DC appropriately for the static control */
  355. hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
  356. /* CreateIC can return NULL in low memory situations */
  357. if (hdc != NULL)
  358. {
  359. hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L);
  360. if (NULL != hfont) // WM_GETFONT returns NULL if window uses system font
  361. hfontOld = (HFONT)SelectObject(hdc, hfont);
  362. /* check horizontal extent of string */
  363. if (GetTextWSize(hdc, lpch) > nWidth || lstrlen(lpch) >= nMaxChars)
  364. Abbreviate(hdc, nWidth, lpch, nMaxChars);
  365. if (NULL != hfont)
  366. SelectObject(hdc, hfontOld);
  367. DeleteDC(hdc);
  368. }
  369. return lpch;
  370. }
  371. /*
  372. * OpenFileError
  373. *
  374. * Purpose:
  375. * display message for error returned from OpenFile
  376. *
  377. * Parameters:
  378. * hDlg HWND of the dialog.
  379. * nErrCode UINT error code returned in OFSTRUCT passed to OpenFile
  380. * lpszFile LPSTR file name passed to OpenFile
  381. *
  382. * Return Value:
  383. * None
  384. */
  385. void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPTSTR lpszFile)
  386. {
  387. switch (nErrCode)
  388. {
  389. case 0x0005: // Access denied
  390. ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILEACCESS, lpszFile,
  391. MB_OK | MB_ICONEXCLAMATION);
  392. break;
  393. case 0x0020: // Sharing violation
  394. ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILESHARE, lpszFile,
  395. MB_OK | MB_ICONEXCLAMATION);
  396. break;
  397. case 0x0002: // File not found
  398. case 0x0003: // Path not found
  399. ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIINVALIDFILE, lpszFile,
  400. MB_OK | MB_ICONEXCLAMATION);
  401. break;
  402. default:
  403. ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILEOPENFAIL, lpszFile,
  404. MB_OK | MB_ICONEXCLAMATION);
  405. break;
  406. }
  407. }
  408. /*
  409. * DoesFileExist
  410. *
  411. * Purpose:
  412. * Determines if a file path exists
  413. *
  414. * Parameters:
  415. * lpszFile LPTSTR - file name
  416. * cchMax UINT - size of the lpszFile string buffer in characters.
  417. *
  418. * Return Value:
  419. * BOOL TRUE if file exists, else FALSE.
  420. *
  421. * NOTE: lpszFile may be changed as a result of this call to match the first
  422. * matching file name found by this routine.
  423. *
  424. */
  425. BOOL WINAPI DoesFileExist(LPTSTR lpszFile, UINT cchMax)
  426. {
  427. static const TCHAR *arrIllegalNames[] =
  428. {
  429. TEXT("LPT1"), TEXT("LPT2"), TEXT("LPT3"),
  430. TEXT("COM1"), TEXT("COM2"), TEXT("COM3"), TEXT("COM4"),
  431. TEXT("CON"), TEXT("AUX"), TEXT("PRN")
  432. };
  433. // check is the name is an illegal name (eg. the name of a device)
  434. for (int i = 0; i < (sizeof(arrIllegalNames)/sizeof(arrIllegalNames[0])); i++)
  435. {
  436. if (lstrcmpi(lpszFile, arrIllegalNames[i])==0)
  437. return FALSE;
  438. }
  439. // First try to find the file with an exact match
  440. // check the file's attributes
  441. DWORD dwAttrs = GetFileAttributes(lpszFile);
  442. if (dwAttrs == 0xFFFFFFFF) // file wasn't found
  443. {
  444. // look in path for file
  445. TCHAR szTempFileName[MAX_PATH];
  446. LPTSTR lpszFilePart;
  447. BOOL fFound = SearchPath(NULL, lpszFile, NULL, MAX_PATH, szTempFileName, &lpszFilePart) != 0;
  448. if (!fFound)
  449. {
  450. // File wasn't found in the search path
  451. // Try to append a .* and use FindFirstFile to try for a match in the current directory
  452. UINT cchFile = lstrlen(lpszFile);
  453. if (cchFile + 4 < MAX_PATH)
  454. {
  455. WIN32_FIND_DATA sFindFileData;
  456. lstrcpy(szTempFileName,lpszFile);
  457. lstrcpy(&szTempFileName[cchFile], TEXT("*.*"));
  458. HANDLE hFindFile = FindFirstFile(szTempFileName, &sFindFileData);
  459. if (INVALID_HANDLE_VALUE != hFindFile)
  460. {
  461. // found something
  462. while (0 != (sFindFileData.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_TEMPORARY)))
  463. {
  464. // found a directory or a temporary file try again
  465. if (!FindNextFile(hFindFile, &sFindFileData))
  466. {
  467. // Could only match a directory or temporary file.
  468. FindClose(hFindFile);
  469. return(FALSE);
  470. }
  471. }
  472. // Copy the name of the found file into the end of the path in the
  473. // temporary buffer (if any).
  474. // First scan back for the last file separator.
  475. UINT cchPath = lstrlen(szTempFileName);
  476. while (cchPath)
  477. {
  478. if (_T('\\') == szTempFileName[cchPath - 1]
  479. || _T('/') == szTempFileName[cchPath - 1])
  480. {
  481. break;
  482. }
  483. cchPath--;
  484. }
  485. lstrcpyn(&szTempFileName[cchPath], sFindFileData.cFileName, MAX_PATH - cchPath);
  486. fFound = TRUE;
  487. FindClose(hFindFile);
  488. }
  489. }
  490. }
  491. if (fFound)
  492. {
  493. // copy the temporary buffer into szFile
  494. lstrcpyn(lpszFile, szTempFileName, cchMax -1);
  495. }
  496. return(fFound);
  497. }
  498. else if (dwAttrs & (FILE_ATTRIBUTE_DIRECTORY|
  499. FILE_ATTRIBUTE_TEMPORARY))
  500. {
  501. return FALSE;
  502. }
  503. return TRUE;
  504. }
  505. /*
  506. * FormatStrings
  507. *
  508. * Purpose:
  509. * Simple message formatting API compatible w/ different languages
  510. *
  511. * Note:
  512. * Shamelessly stolen/modified from MFC source code
  513. *
  514. */
  515. void WINAPI FormatStrings(LPTSTR lpszDest, LPCTSTR lpszFormat,
  516. LPCTSTR* rglpsz, int nString)
  517. {
  518. LPCTSTR pchSrc = lpszFormat;
  519. while (*pchSrc != '\0')
  520. {
  521. if (pchSrc[0] == '%' && (pchSrc[1] >= '1' && pchSrc[1] <= '9'))
  522. {
  523. int i = pchSrc[1] - '1';
  524. pchSrc += 2;
  525. if (i >= nString)
  526. *lpszDest++ = '?';
  527. else if (rglpsz[i] != NULL)
  528. {
  529. lstrcpy(lpszDest, rglpsz[i]);
  530. lpszDest += lstrlen(lpszDest);
  531. }
  532. }
  533. else
  534. {
  535. #ifndef _UNICODE
  536. if (IsDBCSLeadByte(*pchSrc))
  537. *lpszDest++ = *pchSrc++; // copy first of 2 bytes
  538. #endif
  539. *lpszDest++ = *pchSrc++;
  540. }
  541. }
  542. *lpszDest = '\0';
  543. }
  544. void WINAPI FormatString1(LPTSTR lpszDest, LPCTSTR lpszFormat, LPCTSTR lpsz1)
  545. {
  546. FormatStrings(lpszDest, lpszFormat, &lpsz1, 1);
  547. }
  548. void WINAPI FormatString2(LPTSTR lpszDest, LPCTSTR lpszFormat, LPCTSTR lpsz1,
  549. LPCTSTR lpsz2)
  550. {
  551. LPCTSTR rglpsz[2];
  552. rglpsz[0] = lpsz1;
  553. rglpsz[1] = lpsz2;
  554. FormatStrings(lpszDest, lpszFormat, rglpsz, 2);
  555. }
  556. // Replacement for stdlib atol,
  557. // which didn't work and doesn't take far pointers.
  558. // Must be tolerant of leading spaces.
  559. //
  560. //
  561. LONG WINAPI Atol(LPTSTR lpsz)
  562. {
  563. signed int sign = +1;
  564. UINT base = 10;
  565. LONG l = 0;
  566. if (NULL==lpsz)
  567. {
  568. OleDbgAssert (0);
  569. return 0;
  570. }
  571. while (*lpsz == ' ' || *lpsz == '\t' || *lpsz == '\n')
  572. lpsz++;
  573. if (*lpsz=='-')
  574. {
  575. lpsz++;
  576. sign = -1;
  577. }
  578. if (lpsz[0] == TEXT('0') && lpsz[1] == TEXT('x'))
  579. {
  580. base = 16;
  581. lpsz+=2;
  582. }
  583. if (base == 10)
  584. {
  585. while (*lpsz >= '0' && *lpsz <= '9')
  586. {
  587. l = l * base + *lpsz - '0';
  588. lpsz++;
  589. }
  590. }
  591. else
  592. {
  593. OleDbgAssert(base == 16);
  594. while (*lpsz >= '0' && *lpsz <= '9' ||
  595. *lpsz >= 'A' && *lpsz <= 'F' ||
  596. *lpsz >= 'a' && *lpsz <= 'f')
  597. {
  598. l = l * base;
  599. if (*lpsz >= '0' && *lpsz <= '9')
  600. l += *lpsz - '0';
  601. else if (*lpsz >= 'a' && *lpsz <= 'f')
  602. l += *lpsz - 'a' + 10;
  603. else
  604. l += *lpsz - 'A' + 10;
  605. lpsz++;
  606. }
  607. }
  608. return l * sign;
  609. }
  610. BOOL WINAPI IsValidClassID(REFCLSID clsid)
  611. {
  612. return clsid != CLSID_NULL;
  613. }
  614. /* PopupMessage
  615. * ------------
  616. *
  617. * Purpose:
  618. * Popup messagebox and get some response from the user. It is the same
  619. * as MessageBox() except that the title and message string are loaded
  620. * from the resource file.
  621. *
  622. * Parameters:
  623. * hwndParent parent window of message box
  624. * idTitle id of title string
  625. * idMessage id of message string
  626. * fuStyle style of message box
  627. */
  628. int WINAPI PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle)
  629. {
  630. TCHAR szTitle[256];
  631. TCHAR szMsg[256];
  632. LoadString(_g_hOleStdResInst, idTitle, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  633. LoadString(_g_hOleStdResInst, idMessage, szMsg, sizeof(szMsg)/sizeof(TCHAR));
  634. return MessageBox(hwndParent, szMsg, szTitle, fuStyle);
  635. }
  636. /* DiffPrefix
  637. * ----------
  638. *
  639. * Purpose:
  640. * Compare (case-insensitive) two strings and return the prefixes of the
  641. * the strings formed by removing the common suffix string from them.
  642. * Integrity of tokens (directory name, filename and object names) are
  643. * preserved. Note that the prefixes are converted to upper case
  644. * characters.
  645. *
  646. * Parameters:
  647. * lpsz1 string 1
  648. * lpsz2 string 2
  649. * lplpszPrefix1 prefix of string 1
  650. * lplpszPrefix2 prefix of string 2
  651. *
  652. * Returns:
  653. *
  654. */
  655. void WINAPI DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2)
  656. {
  657. LPTSTR lpstr1;
  658. LPTSTR lpstr2;
  659. TCHAR szTemp1[MAX_PATH];
  660. TCHAR szTemp2[MAX_PATH];
  661. OleDbgAssert(lpsz1);
  662. OleDbgAssert(lpsz2);
  663. OleDbgAssert(*lpsz1);
  664. OleDbgAssert(*lpsz2);
  665. OleDbgAssert(lplpszPrefix1);
  666. OleDbgAssert(lplpszPrefix2);
  667. // need to copy into temporary for case insensitive compare
  668. lstrcpy(szTemp1, lpsz1);
  669. lstrcpy(szTemp2, lpsz2);
  670. CharLower(szTemp1);
  671. CharLower(szTemp2);
  672. // do comparison
  673. lpstr1 = szTemp1 + lstrlen(szTemp1);
  674. lpstr2 = szTemp2 + lstrlen(szTemp2);
  675. while ((lpstr1 > szTemp1) && (lpstr2 > szTemp2))
  676. {
  677. lpstr1 = CharPrev(szTemp1, lpstr1);
  678. lpstr2 = CharPrev(szTemp2, lpstr2);
  679. if (*lpstr1 != *lpstr2)
  680. {
  681. lpstr1 = CharNext(lpstr1);
  682. lpstr2 = CharNext(lpstr2);
  683. break;
  684. }
  685. }
  686. // scan forward to first delimiter
  687. while (*lpstr1 && *lpstr1 != '\\' && *lpstr1 != '!')
  688. lpstr1 = CharNext(lpstr1);
  689. while (*lpstr2 && *lpstr2 != '\\' && *lpstr2 != '!')
  690. lpstr2 = CharNext(lpstr2);
  691. *lpstr1 = '\0';
  692. *lpstr2 = '\0';
  693. // initialize in case of failure
  694. *lplpszPrefix1 = NULL;
  695. *lplpszPrefix2 = NULL;
  696. // allocate memory for the result
  697. *lplpszPrefix1 = (LPTSTR)OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(TCHAR));
  698. if (!*lplpszPrefix1)
  699. return;
  700. *lplpszPrefix2 = (LPTSTR)OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(TCHAR));
  701. if (!*lplpszPrefix2)
  702. {
  703. OleStdFree(*lplpszPrefix1);
  704. *lplpszPrefix1 = NULL;
  705. return;
  706. }
  707. // copy result
  708. lstrcpyn(*lplpszPrefix1, lpsz1, lstrlen(szTemp1)+1);
  709. lstrcpyn(*lplpszPrefix2, lpsz2, lstrlen(szTemp2)+1);
  710. }
  711. UINT WINAPI GetFileName(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax)
  712. {
  713. // always capture the complete file name including extension (if present)
  714. LPTSTR lpszTemp = (LPTSTR)lpszPathName;
  715. for (LPCTSTR lpsz = lpszPathName; *lpsz != '\0'; lpsz = CharNext(lpsz))
  716. {
  717. // remember last directory/drive separator
  718. if (*lpsz == '\\' || *lpsz == '/' || *lpsz == ':')
  719. lpszTemp = CharNext(lpsz);
  720. }
  721. // lpszTitle can be NULL which just returns the number of bytes
  722. if (lpszTitle == NULL)
  723. return lstrlen(lpszTemp)+1;
  724. // otherwise copy it into the buffer provided
  725. lstrcpyn(lpszTitle, lpszTemp, nMax);
  726. return 0;
  727. }
  728. BOOL WINAPI IsValidMetaPict(HGLOBAL hMetaPict)
  729. {
  730. BOOL fReturn = FALSE;
  731. LPMETAFILEPICT pMF = (LPMETAFILEPICT) GlobalLock(hMetaPict);
  732. if (pMF != NULL)
  733. {
  734. if (!IsBadReadPtr( pMF, sizeof(METAFILEPICT)))
  735. {
  736. if (GetMetaFileBitsEx(pMF->hMF, 0, 0))
  737. {
  738. fReturn = TRUE;
  739. }
  740. }
  741. GlobalUnlock(hMetaPict);
  742. }
  743. return(fReturn);
  744. }
  745. /////////////////////////////////////////////////////////////////////////////