Windows NT 4.0 source code leak
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.

830 lines
25 KiB

4 years ago
  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. hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L);
  357. if (NULL != hfont) // WM_GETFONT returns NULL if window uses system font
  358. hfontOld = (HFONT)SelectObject(hdc, hfont);
  359. /* check horizontal extent of string */
  360. if (GetTextWSize(hdc, lpch) > nWidth || lstrlen(lpch) >= nMaxChars)
  361. Abbreviate(hdc, nWidth, lpch, nMaxChars);
  362. if (NULL != hfont)
  363. SelectObject(hdc, hfontOld);
  364. DeleteDC(hdc);
  365. return lpch;
  366. }
  367. /*
  368. * OpenFileError
  369. *
  370. * Purpose:
  371. * display message for error returned from OpenFile
  372. *
  373. * Parameters:
  374. * hDlg HWND of the dialog.
  375. * nErrCode UINT error code returned in OFSTRUCT passed to OpenFile
  376. * lpszFile LPSTR file name passed to OpenFile
  377. *
  378. * Return Value:
  379. * None
  380. */
  381. void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPTSTR lpszFile)
  382. {
  383. switch (nErrCode)
  384. {
  385. case 0x0005: // Access denied
  386. ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILEACCESS, lpszFile,
  387. MB_OK | MB_ICONEXCLAMATION);
  388. break;
  389. case 0x0020: // Sharing violation
  390. ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILESHARE, lpszFile,
  391. MB_OK | MB_ICONEXCLAMATION);
  392. break;
  393. case 0x0002: // File not found
  394. case 0x0003: // Path not found
  395. ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIINVALIDFILE, lpszFile,
  396. MB_OK | MB_ICONEXCLAMATION);
  397. break;
  398. default:
  399. ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILEOPENFAIL, lpszFile,
  400. MB_OK | MB_ICONEXCLAMATION);
  401. break;
  402. }
  403. }
  404. /*
  405. * DoesFileExist
  406. *
  407. * Purpose:
  408. * Determines if a file path exists
  409. *
  410. * Parameters:
  411. * lpszFile LPTSTR - file name
  412. * cchMax UINT - size of the lpszFile string buffer in characters.
  413. *
  414. * Return Value:
  415. * BOOL TRUE if file exists, else FALSE.
  416. *
  417. * NOTE: lpszFile may be changed as a result of this call to match the first
  418. * matching file name found by this routine.
  419. *
  420. */
  421. BOOL WINAPI DoesFileExist(LPTSTR lpszFile, UINT cchMax)
  422. {
  423. static const TCHAR *arrIllegalNames[] =
  424. {
  425. TEXT("LPT1"), TEXT("LPT2"), TEXT("LPT3"),
  426. TEXT("COM1"), TEXT("COM2"), TEXT("COM3"), TEXT("COM4"),
  427. TEXT("CON"), TEXT("AUX"), TEXT("PRN")
  428. };
  429. // check is the name is an illegal name (eg. the name of a device)
  430. for (int i = 0; i < (sizeof(arrIllegalNames)/sizeof(arrIllegalNames[0])); i++)
  431. {
  432. if (lstrcmpi(lpszFile, arrIllegalNames[i])==0)
  433. return FALSE;
  434. }
  435. // First try to find the file with an exact match
  436. // check the file's attributes
  437. DWORD dwAttrs = GetFileAttributes(lpszFile);
  438. if (dwAttrs == 0xFFFFFFFF) // file wasn't found
  439. {
  440. // look in path for file
  441. TCHAR szTempFileName[MAX_PATH];
  442. LPTSTR lpszFilePart;
  443. BOOL fFound = SearchPath(NULL, lpszFile, NULL, MAX_PATH, szTempFileName, &lpszFilePart) != 0;
  444. if (!fFound)
  445. {
  446. // File wasn't found in the search path
  447. // Try to append a .* and use FindFirstFile to try for a match in the current directory
  448. UINT cchFile = lstrlen(lpszFile);
  449. if (cchFile + 4 < MAX_PATH)
  450. {
  451. WIN32_FIND_DATA sFindFileData;
  452. lstrcpy(szTempFileName,lpszFile);
  453. lstrcpy(&szTempFileName[cchFile], TEXT("*.*"));
  454. HANDLE hFindFile = FindFirstFile(szTempFileName, &sFindFileData);
  455. if (INVALID_HANDLE_VALUE != hFindFile)
  456. {
  457. // found something
  458. while (0 != sFindFileData.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_TEMPORARY))
  459. {
  460. // found a directory or a temporary file try again
  461. if (!FindNextFile(hFindFile, &sFindFileData))
  462. {
  463. // Could only match a directory or temporary file.
  464. FindClose(hFindFile);
  465. return(FALSE);
  466. }
  467. }
  468. // Copy the name of the found file into the end of the path in the
  469. // temporary buffer (if any).
  470. // First scan back for the last file separator.
  471. UINT cchPath = lstrlen(szTempFileName);
  472. while (cchPath)
  473. {
  474. if (_T('\\') == szTempFileName[cchPath - 1]
  475. || _T('/') == szTempFileName[cchPath - 1])
  476. {
  477. break;
  478. }
  479. cchPath--;
  480. }
  481. lstrcpyn(&szTempFileName[cchPath], sFindFileData.cFileName, MAX_PATH - cchPath);
  482. fFound = TRUE;
  483. FindClose(hFindFile);
  484. }
  485. }
  486. }
  487. if (fFound)
  488. {
  489. // copy the temporary buffer into szFile
  490. lstrcpyn(lpszFile, szTempFileName, cchMax -1);
  491. }
  492. return(fFound);
  493. }
  494. else if (dwAttrs & (FILE_ATTRIBUTE_DIRECTORY|
  495. FILE_ATTRIBUTE_TEMPORARY))
  496. {
  497. return FALSE;
  498. }
  499. return TRUE;
  500. }
  501. /*
  502. * FormatStrings
  503. *
  504. * Purpose:
  505. * Simple message formatting API compatible w/ different languages
  506. *
  507. * Note:
  508. * Shamelessly stolen/modified from MFC source code
  509. *
  510. */
  511. void WINAPI FormatStrings(LPTSTR lpszDest, LPCTSTR lpszFormat,
  512. LPCTSTR* rglpsz, int nString)
  513. {
  514. LPCTSTR pchSrc = lpszFormat;
  515. while (*pchSrc != '\0')
  516. {
  517. if (pchSrc[0] == '%' && (pchSrc[1] >= '1' && pchSrc[1] <= '9'))
  518. {
  519. int i = pchSrc[1] - '1';
  520. pchSrc += 2;
  521. if (i >= nString)
  522. *lpszDest++ = '?';
  523. else if (rglpsz[i] != NULL)
  524. {
  525. lstrcpy(lpszDest, rglpsz[i]);
  526. lpszDest += lstrlen(lpszDest);
  527. }
  528. }
  529. else
  530. {
  531. #ifndef _UNICODE
  532. if (IsDBCSLeadByte(*pchSrc))
  533. *lpszDest++ = *pchSrc++; // copy first of 2 bytes
  534. #endif
  535. *lpszDest++ = *pchSrc++;
  536. }
  537. }
  538. *lpszDest = '\0';
  539. }
  540. void WINAPI FormatString1(LPTSTR lpszDest, LPCTSTR lpszFormat, LPCTSTR lpsz1)
  541. {
  542. FormatStrings(lpszDest, lpszFormat, &lpsz1, 1);
  543. }
  544. void WINAPI FormatString2(LPTSTR lpszDest, LPCTSTR lpszFormat, LPCTSTR lpsz1,
  545. LPCTSTR lpsz2)
  546. {
  547. LPCTSTR rglpsz[2];
  548. rglpsz[0] = lpsz1;
  549. rglpsz[1] = lpsz2;
  550. FormatStrings(lpszDest, lpszFormat, rglpsz, 2);
  551. }
  552. // Replacement for stdlib atol,
  553. // which didn't work and doesn't take far pointers.
  554. // Must be tolerant of leading spaces.
  555. //
  556. //
  557. LONG WINAPI Atol(LPTSTR lpsz)
  558. {
  559. signed int sign = +1;
  560. UINT base = 10;
  561. LONG l = 0;
  562. if (NULL==lpsz)
  563. {
  564. OleDbgAssert (0);
  565. return 0;
  566. }
  567. while (*lpsz == ' ' || *lpsz == '\t' || *lpsz == '\n')
  568. lpsz++;
  569. if (*lpsz=='-')
  570. {
  571. lpsz++;
  572. sign = -1;
  573. }
  574. if (lpsz[0] == TEXT('0') && lpsz[1] == TEXT('x'))
  575. {
  576. base = 16;
  577. lpsz+=2;
  578. }
  579. if (base == 10)
  580. {
  581. while (*lpsz >= '0' && *lpsz <= '9')
  582. {
  583. l = l * base + *lpsz - '0';
  584. lpsz++;
  585. }
  586. }
  587. else
  588. {
  589. OleDbgAssert(base == 16);
  590. while (*lpsz >= '0' && *lpsz <= '9' ||
  591. *lpsz >= 'A' && *lpsz <= 'F' ||
  592. *lpsz >= 'a' && *lpsz <= 'f')
  593. {
  594. l = l * base;
  595. if (*lpsz >= '0' && *lpsz <= '9')
  596. l += *lpsz - '0';
  597. else if (*lpsz >= 'a' && *lpsz <= 'f')
  598. l += *lpsz - 'a' + 10;
  599. else
  600. l += *lpsz - 'A' + 10;
  601. lpsz++;
  602. }
  603. }
  604. return l * sign;
  605. }
  606. BOOL WINAPI IsValidClassID(REFCLSID clsid)
  607. {
  608. return clsid != CLSID_NULL;
  609. }
  610. /* PopupMessage
  611. * ------------
  612. *
  613. * Purpose:
  614. * Popup messagebox and get some response from the user. It is the same
  615. * as MessageBox() except that the title and message string are loaded
  616. * from the resource file.
  617. *
  618. * Parameters:
  619. * hwndParent parent window of message box
  620. * idTitle id of title string
  621. * idMessage id of message string
  622. * fuStyle style of message box
  623. */
  624. int WINAPI PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle)
  625. {
  626. TCHAR szTitle[256];
  627. TCHAR szMsg[256];
  628. LoadString(_g_hOleStdResInst, idTitle, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  629. LoadString(_g_hOleStdResInst, idMessage, szMsg, sizeof(szMsg)/sizeof(TCHAR));
  630. return MessageBox(hwndParent, szMsg, szTitle, fuStyle);
  631. }
  632. /* DiffPrefix
  633. * ----------
  634. *
  635. * Purpose:
  636. * Compare (case-insensitive) two strings and return the prefixes of the
  637. * the strings formed by removing the common suffix string from them.
  638. * Integrity of tokens (directory name, filename and object names) are
  639. * preserved. Note that the prefixes are converted to upper case
  640. * characters.
  641. *
  642. * Parameters:
  643. * lpsz1 string 1
  644. * lpsz2 string 2
  645. * lplpszPrefix1 prefix of string 1
  646. * lplpszPrefix2 prefix of string 2
  647. *
  648. * Returns:
  649. *
  650. */
  651. void WINAPI DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2)
  652. {
  653. LPTSTR lpstr1;
  654. LPTSTR lpstr2;
  655. TCHAR szTemp1[MAX_PATH];
  656. TCHAR szTemp2[MAX_PATH];
  657. OleDbgAssert(lpsz1);
  658. OleDbgAssert(lpsz2);
  659. OleDbgAssert(*lpsz1);
  660. OleDbgAssert(*lpsz2);
  661. OleDbgAssert(lplpszPrefix1);
  662. OleDbgAssert(lplpszPrefix2);
  663. // need to copy into temporary for case insensitive compare
  664. lstrcpy(szTemp1, lpsz1);
  665. lstrcpy(szTemp2, lpsz2);
  666. CharLower(szTemp1);
  667. CharLower(szTemp2);
  668. // do comparison
  669. lpstr1 = szTemp1 + lstrlen(szTemp1);
  670. lpstr2 = szTemp2 + lstrlen(szTemp2);
  671. while ((lpstr1 > szTemp1) && (lpstr2 > szTemp2))
  672. {
  673. lpstr1 = CharPrev(szTemp1, lpstr1);
  674. lpstr2 = CharPrev(szTemp2, lpstr2);
  675. if (*lpstr1 != *lpstr2)
  676. {
  677. lpstr1 = CharNext(lpstr1);
  678. lpstr2 = CharNext(lpstr2);
  679. break;
  680. }
  681. }
  682. // scan forward to first delimiter
  683. while (*lpstr1 && *lpstr1 != '\\' && *lpstr1 != '!')
  684. lpstr1 = CharNext(lpstr1);
  685. while (*lpstr2 && *lpstr2 != '\\' && *lpstr2 != '!')
  686. lpstr2 = CharNext(lpstr2);
  687. *lpstr1 = '\0';
  688. *lpstr2 = '\0';
  689. // initialize in case of failure
  690. *lplpszPrefix1 = NULL;
  691. *lplpszPrefix2 = NULL;
  692. // allocate memory for the result
  693. *lplpszPrefix1 = (LPTSTR)OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(TCHAR));
  694. if (!*lplpszPrefix1)
  695. return;
  696. *lplpszPrefix2 = (LPTSTR)OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(TCHAR));
  697. if (!*lplpszPrefix2)
  698. {
  699. OleStdFree(*lplpszPrefix1);
  700. *lplpszPrefix1 = NULL;
  701. return;
  702. }
  703. // copy result
  704. lstrcpyn(*lplpszPrefix1, lpsz1, lstrlen(szTemp1)+1);
  705. lstrcpyn(*lplpszPrefix2, lpsz2, lstrlen(szTemp2)+1);
  706. }
  707. UINT WINAPI GetFileName(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax)
  708. {
  709. // always capture the complete file name including extension (if present)
  710. LPTSTR lpszTemp = (LPTSTR)lpszPathName;
  711. for (LPCTSTR lpsz = lpszPathName; *lpsz != '\0'; lpsz = CharNext(lpsz))
  712. {
  713. // remember last directory/drive separator
  714. if (*lpsz == '\\' || *lpsz == '/' || *lpsz == ':')
  715. lpszTemp = CharNext(lpsz);
  716. }
  717. // lpszTitle can be NULL which just returns the number of bytes
  718. if (lpszTitle == NULL)
  719. return lstrlen(lpszTemp)+1;
  720. // otherwise copy it into the buffer provided
  721. lstrcpyn(lpszTitle, lpszTemp, nMax);
  722. return 0;
  723. }
  724. BOOL WINAPI IsValidMetaPict(HGLOBAL hMetaPict)
  725. {
  726. BOOL fReturn = FALSE;
  727. LPMETAFILEPICT pMF = (LPMETAFILEPICT) GlobalLock(hMetaPict);
  728. if (pMF != NULL)
  729. {
  730. if (!IsBadReadPtr( pMF, sizeof(METAFILEPICT)))
  731. {
  732. if (GetMetaFileBitsEx(pMF->hMF, 0, 0))
  733. {
  734. fReturn = TRUE;
  735. }
  736. }
  737. GlobalUnlock(hMetaPict);
  738. }
  739. return(fReturn);
  740. }
  741. /////////////////////////////////////////////////////////////////////////////