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.

879 lines
23 KiB

  1. /*++
  2. Copyright (c) 1990-1998, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. parse.c
  5. Abstract:
  6. This module contains the parse routines for the Win32 common dialogs.
  7. Revision History:
  8. --*/
  9. // precompiled headers
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #include "fileopen.h"
  13. ////////////////////////////////////////////////////////////////////////////
  14. //
  15. // ParseFileNew
  16. //
  17. // On the return, pnExtOffset is the offset to the dot.
  18. //
  19. ////////////////////////////////////////////////////////////////////////////
  20. int ParseFileNew(
  21. LPTSTR pszPath,
  22. int *pnExtOffset,
  23. BOOL bWowApp,
  24. BOOL bNewStyle)
  25. {
  26. int lRet = ParseFile(pszPath, TRUE, bWowApp, bNewStyle);
  27. if (pnExtOffset)
  28. {
  29. int nExt;
  30. nExt = (int)(SHORT)HIWORD(lRet);
  31. *pnExtOffset = ((nExt) && *(pszPath + nExt)) ? nExt : 0;
  32. }
  33. return ((int)(SHORT)LOWORD(lRet));
  34. }
  35. ////////////////////////////////////////////////////////////////////////////
  36. //
  37. // ParseFileOld
  38. //
  39. // On return, pnExtOffset is the offset to the the dot and
  40. // pnOldExt is the offset to the character following the dot.
  41. //
  42. ////////////////////////////////////////////////////////////////////////////
  43. int ParseFileOld(
  44. LPTSTR pszPath,
  45. int *pnExtOffset,
  46. int *pnOldExt,
  47. BOOL bWowApp,
  48. BOOL bNewStyle)
  49. {
  50. int lRet = ParseFile(pszPath, TRUE, bWowApp, bNewStyle);
  51. int nExt = (int)(SHORT)HIWORD(lRet);
  52. *pnExtOffset = nExt;
  53. *pnOldExt = ((nExt) && *(pszPath + nExt)) ? nExt + 1 : 0;
  54. return ((int)(SHORT)LOWORD(lRet));
  55. }
  56. ////////////////////////////////////////////////////////////////////////////
  57. //
  58. // ParseFile
  59. //
  60. // Determines if the filename is a legal dos name.
  61. //
  62. // Circumstances checked:
  63. // 1) Valid as directory name, but not as file name
  64. // 2) Empty String
  65. // 3) Illegal Drive label
  66. // 4) Period in invalid location (in extension, 1st in file name)
  67. // 5) Missing directory character
  68. // 6) Illegal character
  69. // 7) Wildcard in directory name
  70. // 8) Double slash beyond 1st 2 characters
  71. // 9) Space character in the middle of the name (trailing spaces OK)
  72. // -->> no longer applies : spaces are allowed in LFN
  73. // 10) Filename greater than 8 characters : NOT APPLICABLE TO LONG FILE NAMES
  74. // 11) Extension greater than 3 characters: NOT APPLICABLE TO LONG FILE NAMES
  75. //
  76. // lpstrFileName - ptr to a single file name
  77. //
  78. // Returns:
  79. // LONG - LOWORD = char offset to filename,
  80. // HIWORD = char offset to extension (dot),
  81. // LONG - LOWORD is error code (<0), HIWORD is approx. place of problem
  82. //
  83. ////////////////////////////////////////////////////////////////////////////
  84. DWORD ParseFile(
  85. LPTSTR lpstrFileName,
  86. BOOL bLFNFileSystem,
  87. BOOL bWowApp,
  88. BOOL bNewStyle)
  89. {
  90. SHORT nFile, nExt, nFileOffset, nExtOffset = 0;
  91. BOOL bExt;
  92. BOOL bWildcard;
  93. SHORT nNetwork = 0;
  94. BOOL bUNCPath = FALSE;
  95. LPTSTR lpstr = lpstrFileName;
  96. //Check if the string is empty
  97. if (!*lpstr)
  98. {
  99. nFileOffset = PARSE_EMPTYSTRING;
  100. goto ParseFile_Failure;
  101. }
  102. //Check if the string is of form c:\foo1\foo2
  103. if (*(lpstr + 1) == CHAR_COLON)
  104. {
  105. //Yes. Get the drive letter
  106. TCHAR cDrive = CharLowerChar(*lpstr);
  107. //
  108. // Test to see if the drive is legal.
  109. //
  110. // Note: Does not test that drive exists.
  111. //
  112. if ((cDrive < CHAR_A) || (cDrive > CHAR_Z))
  113. {
  114. nFileOffset = PARSE_INVALIDDRIVE;
  115. goto ParseFile_Failure;
  116. }
  117. //Move string past drive letter and ':'
  118. lpstr = CharNext(CharNext(lpstr));
  119. }
  120. if ((*lpstr == CHAR_BSLASH) || (*lpstr == CHAR_SLASH && !bNewStyle))
  121. {
  122. //
  123. // Cannot have "c:\."
  124. //
  125. if (*++lpstr == CHAR_DOT)
  126. {
  127. //
  128. // Except that "c:\.\" is allowed.
  129. //
  130. if ((*++lpstr != CHAR_BSLASH) && (*lpstr != CHAR_SLASH || bNewStyle))
  131. {
  132. //
  133. // It's the root directory.
  134. //
  135. if (!*lpstr)
  136. {
  137. goto MustBeDir;
  138. }
  139. else
  140. {
  141. lpstr--;
  142. }
  143. }
  144. else
  145. {
  146. //
  147. // It's saying top dir (once again), thus allowed.
  148. //
  149. ++lpstr;
  150. }
  151. }
  152. else if ((*lpstr == CHAR_BSLASH) && (*(lpstr - 1) == CHAR_BSLASH))
  153. {
  154. //
  155. // It seems that for a full network path, whether a drive is
  156. // declared or not is insignificant, though if a drive is given,
  157. // it must be valid (hence the code above should remain there).
  158. //
  159. //
  160. // ...since it's the first slash, 2 are allowed.
  161. //
  162. ++lpstr;
  163. //
  164. // Must receive server and share to be real.
  165. //
  166. nNetwork = -1;
  167. //
  168. // No wildcards allowed if UNC name.
  169. //
  170. bUNCPath = TRUE;
  171. }
  172. else if (*lpstr == CHAR_SLASH && !bNewStyle)
  173. {
  174. nFileOffset = PARSE_INVALIDDIRCHAR;
  175. goto ParseFile_Failure;
  176. }
  177. }
  178. else if (*lpstr == CHAR_DOT)
  179. {
  180. //
  181. // Up one directory.
  182. //
  183. if (*++lpstr == CHAR_DOT)
  184. {
  185. ++lpstr;
  186. }
  187. if (!*lpstr)
  188. {
  189. goto MustBeDir;
  190. }
  191. if ((*lpstr != CHAR_BSLASH) && (*lpstr != CHAR_SLASH || bNewStyle))
  192. {
  193. //
  194. // Jumping to Failure here will skip the parsing that causes
  195. // ".xxx.txt" to return with nFileOffset = 2.
  196. //
  197. nFileOffset = 0;
  198. goto ParseFile_Failure;
  199. }
  200. else
  201. {
  202. //
  203. // Allow directory.
  204. //
  205. ++lpstr;
  206. }
  207. }
  208. if (!*lpstr)
  209. {
  210. goto MustBeDir;
  211. }
  212. //
  213. // Should point to first char in filename by now.
  214. //
  215. nFileOffset = nExtOffset = nFile = nExt = 0;
  216. bWildcard = bExt = FALSE;
  217. while (*lpstr)
  218. {
  219. //
  220. // Anything below the "Space" character is invalid.
  221. //
  222. if (*lpstr < CHAR_SPACE)
  223. {
  224. nFileOffset = PARSE_INVALIDCHAR;
  225. goto ParseFile_Failure;
  226. }
  227. switch (*lpstr)
  228. {
  229. case ( CHAR_COLON ) :
  230. case ( CHAR_BAR ) :
  231. case ( CHAR_LTHAN ) :
  232. case ( CHAR_QUOTE ) :
  233. {
  234. //
  235. // Invalid characters for all file systems.
  236. //
  237. nFileOffset = PARSE_INVALIDCHAR;
  238. goto ParseFile_Failure;
  239. }
  240. case ( CHAR_SEMICOLON ) :
  241. case ( CHAR_COMMA ) :
  242. case ( CHAR_PLUS ) :
  243. case ( CHAR_LBRACKET ) :
  244. case ( CHAR_RBRACKET ) :
  245. case ( CHAR_EQUAL ) :
  246. {
  247. if (!bLFNFileSystem)
  248. {
  249. nFileOffset = PARSE_INVALIDCHAR;
  250. goto ParseFile_Failure;
  251. }
  252. else
  253. {
  254. goto RegularCharacter;
  255. }
  256. }
  257. case ( CHAR_SLASH ) :
  258. {
  259. if (bNewStyle)
  260. {
  261. nFileOffset = PARSE_INVALIDCHAR;
  262. goto ParseFile_Failure;
  263. }
  264. // fall thru...
  265. }
  266. case ( CHAR_BSLASH ) :
  267. {
  268. //
  269. // Subdir indicators.
  270. //
  271. nNetwork++;
  272. if (bWildcard)
  273. {
  274. nFileOffset = PARSE_WILDCARDINDIR;
  275. goto ParseFile_Failure;
  276. }
  277. //
  278. // if nFile==0 means that we are seeing this backslash right next to a backslash
  279. // which is not allowed.
  280. if (nFile == 0)
  281. {
  282. nFileOffset = PARSE_INVALIDDIRCHAR;
  283. goto ParseFile_Failure;
  284. }
  285. else
  286. {
  287. //Move over the BSLASH/SLASH character.
  288. ++lpstr;
  289. //Check if the path is valid network path name
  290. if (!nNetwork && !*lpstr)
  291. {
  292. nFileOffset = PARSE_INVALIDNETPATH;
  293. goto ParseFile_Failure;
  294. }
  295. //We assume that the characters we are seeing are filename characters. This BSLASH/SLASH
  296. //character tells that characters we have seen so far specifies the name of a directory in the
  297. //path. Reset flags so that we can start looking for filename again.
  298. nFile = nExt = 0;
  299. nExtOffset = 0;
  300. bExt = FALSE;
  301. }
  302. break;
  303. }
  304. case ( CHAR_SPACE ) :
  305. {
  306. LPTSTR lpSpace = lpstr;
  307. if (bLFNFileSystem)
  308. {
  309. // In Long file name file system space characters are O.K
  310. goto RegularCharacter;
  311. }
  312. //We are not interested in the trailing spaces so null terminate it.
  313. *lpSpace = CHAR_NULL;
  314. // In non long file name file systems, space characters are OK at the end of file
  315. // name. Check to see if all the characters that follows are spaces. if thats the case
  316. // then its valid. if we have any non space character after the first space then its a
  317. // invalid file name.
  318. while (*++lpSpace)
  319. {
  320. if (*lpSpace != CHAR_SPACE)
  321. {
  322. *lpstr = CHAR_SPACE;
  323. nFileOffset = PARSE_INVALIDSPACE;
  324. goto ParseFile_Failure;
  325. }
  326. }
  327. break;
  328. }
  329. case ( CHAR_DOT ) :
  330. {
  331. // In newstyle nExtOffset points to the dot and not to the first character of extension.
  332. if (bNewStyle)
  333. {
  334. nExtOffset = (SHORT)(lpstr - lpstrFileName);
  335. goto RegularCharacter;
  336. }
  337. if (nFile == 0)
  338. {
  339. nFileOffset = (SHORT)(lpstr - lpstrFileName);
  340. if (*++lpstr == CHAR_DOT)
  341. {
  342. ++lpstr;
  343. }
  344. if (!*lpstr)
  345. {
  346. goto MustBeDir;
  347. }
  348. //
  349. // Flags already set.
  350. //
  351. nFile++;
  352. ++lpstr;
  353. }
  354. else
  355. {
  356. nExtOffset = 0;
  357. ++lpstr;
  358. bExt = TRUE;
  359. }
  360. break;
  361. }
  362. case ( CHAR_STAR ) :
  363. case ( CHAR_QMARK ) :
  364. {
  365. bWildcard = TRUE;
  366. // Fall thru...
  367. }
  368. default :
  369. {
  370. RegularCharacter:
  371. //Are we in extension part ?
  372. if (bExt)
  373. {
  374. //Is this first character in extension part
  375. if (++nExt == 1)
  376. {
  377. //Yes, then get the Extension offset
  378. nExtOffset = (SHORT)(lpstr - lpstrFileName);
  379. }
  380. }
  381. //We are still in file name part.
  382. //Is this the first character in filename part ?
  383. else if (++nFile == 1)
  384. {
  385. //Yes. Get the filename offset
  386. nFileOffset = (SHORT)(lpstr - lpstrFileName);
  387. }
  388. //Move to the next character
  389. lpstr = CharNext(lpstr);
  390. break;
  391. }
  392. }
  393. }
  394. if (nNetwork == -1)
  395. {
  396. nFileOffset = PARSE_INVALIDNETPATH;
  397. goto ParseFile_Failure;
  398. }
  399. else if (bUNCPath)
  400. {
  401. if (!nNetwork)
  402. {
  403. //
  404. // Server and share only.(e.g \\server\foo)
  405. //
  406. *lpstr = CHAR_NULL;
  407. nFileOffset = PARSE_DIRECTORYNAME;
  408. goto ParseFile_Failure;
  409. }
  410. else if ((nNetwork == 1) && !nFile)
  411. {
  412. //
  413. // Server and share root.(e.g \\server\foo\)
  414. //
  415. *lpstr = CHAR_NULL;
  416. nFileOffset = PARSE_DIRECTORYNAME;
  417. goto ParseFile_Failure;
  418. }
  419. }
  420. if (!nFile)
  421. {
  422. MustBeDir:
  423. nFileOffset = PARSE_DIRECTORYNAME;
  424. goto ParseFile_Failure;
  425. }
  426. //
  427. // If bNewStyle is true, no ext. wanted.
  428. //
  429. if (!bNewStyle)
  430. {
  431. if ((bWowApp) &&
  432. (*(lpstr - 1) == CHAR_DOT) &&
  433. (*CharNext(lpstr - 2) == CHAR_DOT))
  434. {
  435. //
  436. // Remove terminating period.
  437. //
  438. *(lpstr - 1) = CHAR_NULL;
  439. }
  440. else if (!nExt)
  441. {
  442. ParseFile_Failure:
  443. //
  444. // Need to recheck bNewStyle since we can jump here.
  445. //
  446. if (!bNewStyle)
  447. {
  448. nExtOffset = (SHORT)(lpstr - lpstrFileName);
  449. }
  450. }
  451. }
  452. return (MAKELONG(nFileOffset, nExtOffset));
  453. }
  454. ////////////////////////////////////////////////////////////////////////////
  455. //
  456. // PathRemoveBslash
  457. //
  458. // Removes a trailing backslash from the given path.
  459. //
  460. // Returns:
  461. // Pointer to NULL that replaced the backslash OR
  462. // Pointer to the last character if it isn't a backslash
  463. //
  464. ////////////////////////////////////////////////////////////////////////////
  465. LPTSTR PathRemoveBslash(
  466. LPTSTR lpszPath)
  467. {
  468. int len = lstrlen(lpszPath) - 1;
  469. #ifndef UNICODE
  470. if (IsDBCSLeadByte(*CharPrev(lpszPath, lpszPath + len + 1)))
  471. {
  472. len--;
  473. }
  474. #endif
  475. if (!PathIsRoot(lpszPath) && (lpszPath[len] == CHAR_BSLASH))
  476. {
  477. lpszPath[len] = CHAR_NULL;
  478. }
  479. return (lpszPath + len);
  480. }
  481. ////////////////////////////////////////////////////////////////////////////
  482. //
  483. // IsWild
  484. //
  485. ////////////////////////////////////////////////////////////////////////////
  486. BOOL IsWild(
  487. LPCTSTR lpsz)
  488. {
  489. return (StrChr(lpsz, CHAR_STAR) || StrChr(lpsz, CHAR_QMARK));
  490. }
  491. ////////////////////////////////////////////////////////////////////////////
  492. //
  493. // AppendExt
  494. //
  495. // Appends default extension onto path name.
  496. // It assumes the current path name doesn't already have an extension.
  497. // lpExtension does not need to be null terminated.
  498. //
  499. // Returns TRUE upon succes, otherwise FALSE (not enough buffer room),
  500. //
  501. ////////////////////////////////////////////////////////////////////////////
  502. BOOL AppendExt(
  503. LPTSTR lpszPath,
  504. DWORD cchPath,
  505. LPCTSTR lpExtension,
  506. BOOL bWildcard)
  507. {
  508. WORD wOffset;
  509. SHORT i;
  510. TCHAR szExt[MAX_PATH + 1];
  511. BOOL bRet = TRUE;
  512. if (lpExtension && *lpExtension)
  513. {
  514. wOffset = (WORD)lstrlen(lpszPath);
  515. if (bWildcard)
  516. {
  517. if (wOffset < (cchPath - 1))
  518. {
  519. *(lpszPath + wOffset) = CHAR_STAR;
  520. wOffset++;
  521. }
  522. else
  523. {
  524. bRet = FALSE;
  525. }
  526. }
  527. if (bRet)
  528. {
  529. //
  530. // Add a period.
  531. //
  532. if (wOffset < (cchPath - 1))
  533. {
  534. *(lpszPath + wOffset) = CHAR_DOT;
  535. wOffset++;
  536. }
  537. else
  538. {
  539. bRet = FALSE;
  540. }
  541. if (bRet)
  542. {
  543. for (i = 0; *(lpExtension + i) && i < MAX_PATH; i++)
  544. {
  545. szExt[i] = *(lpExtension + i);
  546. }
  547. szExt[i] = 0;
  548. //
  549. // Remove leading / trailing blanks in the extension.
  550. //
  551. PathRemoveBlanks(szExt);
  552. //
  553. // Add the rest.
  554. //
  555. bRet = SUCCEEDED(StringCchCopy(lpszPath + wOffset, (cchPath - wOffset), szExt));
  556. }
  557. }
  558. }
  559. return bRet;
  560. }
  561. ////////////////////////////////////////////////////////////////////////////
  562. //
  563. // IsUNC
  564. //
  565. // Determines if the given path is a UNC path.
  566. //
  567. // Returns:
  568. // TRUE if path starts with "\\" or "X:\\"
  569. // FALSE otherwise
  570. //
  571. ////////////////////////////////////////////////////////////////////////////
  572. BOOL IsUNC(
  573. LPCTSTR lpszPath)
  574. {
  575. return ( DBL_BSLASH(lpszPath) ||
  576. ((lpszPath[1] == CHAR_COLON) && DBL_BSLASH(lpszPath + 2)) );
  577. }
  578. ////////////////////////////////////////////////////////////////////////////
  579. //
  580. // PortName
  581. //
  582. ////////////////////////////////////////////////////////////////////////////
  583. #define PORTARRAY 14
  584. BOOL PortName(
  585. LPTSTR lpszFileName)
  586. {
  587. static TCHAR *szPorts[PORTARRAY] = { TEXT("LPT1"),
  588. TEXT("LPT2"),
  589. TEXT("LPT3"),
  590. TEXT("LPT4"),
  591. TEXT("COM1"),
  592. TEXT("COM2"),
  593. TEXT("COM3"),
  594. TEXT("COM4"),
  595. TEXT("EPT"),
  596. TEXT("NUL"),
  597. TEXT("PRN"),
  598. TEXT("CLOCK$"),
  599. TEXT("CON"),
  600. TEXT("AUX"),
  601. };
  602. short i;
  603. TCHAR cSave, cSave2;
  604. cSave = *(lpszFileName + 4);
  605. if (cSave == CHAR_DOT)
  606. {
  607. *(lpszFileName + 4) = CHAR_NULL;
  608. }
  609. //
  610. // For "EPT".
  611. //
  612. cSave2 = *(lpszFileName + 3);
  613. if (cSave2 == CHAR_DOT)
  614. {
  615. *(lpszFileName + 3) = CHAR_NULL;
  616. }
  617. for (i = 0; i < PORTARRAY; i++)
  618. {
  619. if (!lstrcmpi(szPorts[i], lpszFileName))
  620. {
  621. break;
  622. }
  623. }
  624. *(lpszFileName + 4) = cSave;
  625. *(lpszFileName + 3) = cSave2;
  626. return (i != PORTARRAY);
  627. }
  628. ////////////////////////////////////////////////////////////////////////////
  629. //
  630. // IsDirectory
  631. //
  632. ////////////////////////////////////////////////////////////////////////////
  633. BOOL IsDirectory(
  634. LPTSTR pszPath)
  635. {
  636. DWORD dwAttributes;
  637. //
  638. // Clean up for GetFileAttributes.
  639. //
  640. PathRemoveBslash(pszPath);
  641. dwAttributes = GetFileAttributes(pszPath);
  642. return ( (dwAttributes != (DWORD)(-1)) &&
  643. (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) );
  644. }
  645. ////////////////////////////////////////////////////////////////////////////
  646. //
  647. // WriteProtectedDirCheck
  648. //
  649. // This function takes a full filename, strips the path, and creates
  650. // a temp file in that directory. If it can't, the directory is probably
  651. // write protected.
  652. //
  653. // Returns:
  654. // error code if writeprotected
  655. // 0 if successful creation of file.
  656. //
  657. // Assumptions:
  658. // Full Path name on input with space for full filename appended.
  659. //
  660. // Note: Do NOT use this on a floppy, it's too slow!
  661. //
  662. ////////////////////////////////////////////////////////////////////////////
  663. int WriteProtectedDirCheck(
  664. LPCTSTR lpszFile)
  665. {
  666. SHORT nFileOffset;
  667. TCHAR szFile[MAX_PATH + 1];
  668. TCHAR szBuf[MAX_PATH + 1];
  669. DWORD dwRet;
  670. EVAL(SUCCEEDED(StringCchCopy(szFile, ARRAYSIZE(szFile), lpszFile)));
  671. dwRet = ParseFile(szFile, TRUE, FALSE, TRUE);
  672. nFileOffset = (SHORT)LOWORD(dwRet);
  673. ASSERT(nFileOffset > 0);
  674. szFile[nFileOffset - 1] = CHAR_NULL;
  675. if (!GetTempFileName(szFile, TEXT("TMP"), 0, szBuf))
  676. {
  677. return (GetLastError());
  678. }
  679. else
  680. {
  681. DeleteFile(szBuf);
  682. return (0); // success
  683. }
  684. }
  685. ////////////////////////////////////////////////////////////////////////////
  686. //
  687. // FOkToWriteOver
  688. //
  689. // Verifies that the user really does want to destroy the file,
  690. // replacing its contents with new stuff.
  691. //
  692. ////////////////////////////////////////////////////////////////////////////
  693. BOOL FOkToWriteOver(
  694. HWND hDlg,
  695. LPTSTR szFileName)
  696. {
  697. TCHAR szCaption[128];
  698. TCHAR szWarning[128 + MAX_FULLPATHNAME];
  699. BOOL bRet = FALSE;
  700. if (CDLoadString( g_hinst,
  701. iszOverwriteQuestion,
  702. szCaption,
  703. ARRAYSIZE(szCaption)))
  704. {
  705. //
  706. // Since we're passed in a valid filename, if the 3rd & 4th characters
  707. // are both slashes, weve got a dummy drive as the 1st two characters.
  708. //
  709. if (DBL_BSLASH(szFileName + 2))
  710. {
  711. szFileName = szFileName + 2;
  712. }
  713. if (SUCCEEDED(StringCchPrintf(szWarning, ARRAYSIZE(szWarning), szCaption, szFileName)))
  714. {
  715. GetWindowText(hDlg, szCaption, ARRAYSIZE(szCaption));
  716. bRet = (MessageBox( hDlg,
  717. szWarning,
  718. szCaption,
  719. MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION ) == IDYES);
  720. }
  721. }
  722. return bRet;
  723. }
  724. ////////////////////////////////////////////////////////////////////////////
  725. //
  726. // CreateFileDlg
  727. //
  728. ////////////////////////////////////////////////////////////////////////////
  729. int CreateFileDlg(
  730. HWND hDlg,
  731. LPTSTR szPath)
  732. {
  733. TCHAR szCaption[128];
  734. TCHAR szWarning[128 + MAX_FULLPATHNAME];
  735. int nRet = IDNO;
  736. //
  737. // Since we're passed in a valid filename, if the 3rd & 4th
  738. // characters are both slashes, we've got a dummy drive as the
  739. // 1st two characters.
  740. //
  741. if (DBL_BSLASH(szPath + 2))
  742. {
  743. szPath = szPath + 2;
  744. }
  745. if (CDLoadString(g_hinst, iszCreatePrompt, szCaption, ARRAYSIZE(szCaption)))
  746. {
  747. if (lstrlen(szPath) > TOOLONGLIMIT)
  748. {
  749. *(szPath + TOOLONGLIMIT) = CHAR_NULL;
  750. }
  751. if (SUCCEEDED(StringCchPrintf(szWarning, ARRAYSIZE(szWarning), szCaption, szPath)))
  752. {
  753. GetWindowText(hDlg, szCaption, ARRAYSIZE(szCaption));
  754. nRet = (MessageBox( hDlg,
  755. szWarning,
  756. szCaption,
  757. MB_YESNO | MB_ICONQUESTION ));
  758. }
  759. }
  760. return nRet;
  761. }