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.

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