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.

1665 lines
48 KiB

  1. // --------------------------------------------------------------------------------
  2. // OERTUTIL.CPP
  3. // --------------------------------------------------------------------------------
  4. #include "pch.hxx"
  5. #include "dllmain.h"
  6. #undef BADSTRFUNCTIONS_H
  7. #undef lstrcpyA
  8. #undef lstrcpy
  9. #define lstrcpy lstrcpyA
  10. #include <BadStrFunctions.h>
  11. #include "strconst.h"
  12. #include <shlwapi.h>
  13. #include <shlwapip.h>
  14. #include <richedit.h>
  15. #include <shlobj.h>
  16. #include <shlobjp.h>
  17. #include <mshtmhst.h>
  18. #include "demand.h"
  19. #include "hotwiz.h"
  20. #include "unicnvrt.h"
  21. #include "comctrlp.h"
  22. int BrowseCallbackProcA(HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData);
  23. int BrowseCallbackProcW(HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData);
  24. typedef struct tagBROWSEFOLDERINFOA
  25. {
  26. LPCSTR psz;
  27. BOOL fFileSysOnly;
  28. } BROWSEFOLDERINFOA;
  29. typedef struct tagBROWSEFOLDERINFOW
  30. {
  31. LPCWSTR pwsz;
  32. BOOL fFileSysOnly;
  33. } BROWSEFOLDERINFOW;
  34. //// YST FIX
  35. // This function returns unique and unpredictable path for temporary files.
  36. // It fixes some security problem when hacker can run ActiveSetup in known directory, when user open attachment.
  37. // For fix this we try to save temporery attachment file in unknown directory: in URL Cache dir.
  38. // This function returns only directory name and user must create and remove file by self.
  39. // it has also theoretical possibility to loose data at time
  40. DWORD AthGetTempUniquePathW( DWORD nBufferLength, // size, in characters, of the buffer
  41. LPWSTR pwszBuffer ) // pointer to buffer for temp. path
  42. {
  43. DWORD nRequired = 0;
  44. CHAR szBuffer[MAX_PATH + 20];
  45. LPWSTR pwszBufferToFree = NULL;
  46. CHAR pszFilePath[MAX_PATH + 1];
  47. CHAR szFileName[MAX_PATH];
  48. LPSTR pszFile = NULL;
  49. LPSTR pszExt = NULL;
  50. Assert(pwszBuffer);
  51. //1. Create unique temp file name
  52. // Get Temp Dir
  53. if(0 == GetTempPathA(ARRAYSIZE(szBuffer), szBuffer))
  54. goto err;
  55. if (0 == GetTempFileName(szBuffer, "wbk", 0, (LPSTR) pszFilePath))
  56. {
  57. err:
  58. nRequired = 0;
  59. *pwszBuffer = 0;
  60. return(nRequired);
  61. }
  62. // Find the filename
  63. pszFile = PathFindFileName(pszFilePath);
  64. // Get the Extension
  65. pszExt = PathFindExtension(pszFilePath);
  66. // Copy fileName
  67. if (pszExt && pszFile && pszExt >= pszFile)
  68. StrCpyN(szFileName, pszFile, (DWORD) (min((pszExt - pszFile) + 1, ARRAYSIZE(szFileName))));
  69. else
  70. StrCpyN(szFileName, pszFile, ARRAYSIZE(szFileName));
  71. // 2. Create bigus URL
  72. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), "http://%s.bogus", szFileName);
  73. szBuffer[ARRAYSIZE(szBuffer) - 1] = 0;
  74. // 3. Create bogus URL cache entry
  75. szFileName[0] = 0;
  76. if (!CreateUrlCacheEntry(szBuffer, 0, NULL, szFileName, 0))
  77. goto err;
  78. // DeleteUrlCacheEntry(szFileName);
  79. // Find path for cache
  80. pszFile = PathFindFileName(szFileName);
  81. if(pszFile)
  82. *pszFile = '\0';
  83. pwszBufferToFree = PszToUnicode(CP_ACP, szFileName);
  84. if (pwszBufferToFree)
  85. {
  86. nRequired = lstrlenW(pwszBufferToFree);
  87. if ( nRequired < nBufferLength)
  88. CopyMemory(pwszBuffer, pwszBufferToFree, (nRequired+1)*sizeof(WCHAR) );
  89. else
  90. {
  91. nRequired = 0;
  92. *pwszBuffer = 0;
  93. }
  94. }
  95. else
  96. *pwszBuffer = 0;
  97. // Cleanup
  98. MemFree(pwszBufferToFree);
  99. DeleteFile(pszFilePath); // GetTempFileName creates file and we need to remove it
  100. return nRequired;
  101. }
  102. /// END YST FIX
  103. // --------------------------------------------------------------------------------
  104. // GenerateUniqueFileName
  105. // --------------------------------------------------------------------------------
  106. OESTDAPI_(HRESULT) GenerateUniqueFileName(LPCSTR pszDirectory, LPCSTR pszFileName, LPCSTR pszExtension,
  107. LPSTR pszFilePath, ULONG cchMaxPath)
  108. {
  109. // Locals
  110. HRESULT hr=S_OK;
  111. ULONG cchDirectory;
  112. ULONG cchFileName;
  113. ULONG cchExtension;
  114. CHAR szUnique[10];
  115. ULONG cchUnique;
  116. ULONG cbEstimate;
  117. HANDLE hTemp=INVALID_HANDLE_VALUE;
  118. DWORD cUnique=0;
  119. DWORD dwLastError;
  120. LPCSTR pszSlash;
  121. // Invalid Arg
  122. Assert(pszDirectory && pszFileName && pszExtension && pszFilePath);
  123. // Compute lengths
  124. *szUnique = '\0';
  125. cchDirectory = lstrlen(pszDirectory);
  126. cchFileName = lstrlen(pszFileName);
  127. cchExtension = lstrlen(pszExtension);
  128. // Set pszSplashes
  129. if ('\\' == *CharPrev(pszDirectory, pszDirectory + cchDirectory))
  130. pszSlash = "";
  131. else
  132. pszSlash = "\\";
  133. // Try to create the file
  134. while(1)
  135. {
  136. // Compute length of unique post fix
  137. cchUnique = lstrlen(szUnique);
  138. // Do I have room + 1 (
  139. cbEstimate = cchDirectory + cchFileName + cchExtension + cchUnique;
  140. // Too Big
  141. if (cbEstimate + 1 > cchMaxPath)
  142. {
  143. LengFail:
  144. Assert(FALSE);
  145. hr = TrapError(E_FAIL);
  146. goto exit;
  147. }
  148. while(cbEstimate > (MAX_PATH - 4))
  149. {
  150. if((cchUnique + cchDirectory) >= (MAX_PATH - 7))
  151. goto LengFail;
  152. else if(cchFileName > 2)
  153. {
  154. pszFileName = CharNext(pszFileName);
  155. cchFileName = lstrlen(pszFileName);
  156. }
  157. else if(cchExtension > 2)
  158. {
  159. pszExtension = CharNext(pszExtension);
  160. cchExtension = lstrlen(pszExtension);
  161. }
  162. else
  163. goto LengFail;
  164. cbEstimate = cchDirectory + cchFileName + cchExtension + cchUnique;
  165. }
  166. // Build the file path
  167. if (0 == cchUnique)
  168. wnsprintf(pszFilePath, cchMaxPath, "%s%s%s%s", pszDirectory, pszSlash, pszFileName, pszExtension);
  169. else
  170. wnsprintf(pszFilePath, cchMaxPath, "%s%s%s (%s)%s", pszDirectory, pszSlash, pszFileName, szUnique, pszExtension);
  171. // Open the File
  172. hTemp = CreateFile(pszFilePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL , NULL);
  173. if (INVALID_HANDLE_VALUE != hTemp)
  174. {
  175. // confirm that what we had is a file
  176. CloseHandle(hTemp);
  177. hTemp = INVALID_HANDLE_VALUE;
  178. if (DeleteFile(pszFilePath))
  179. {
  180. hTemp = CreateFile(pszFilePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL , NULL);
  181. break;
  182. }
  183. }
  184. // Get the last error
  185. dwLastError = GetLastError();
  186. // If it didn't fail because ERROR_ALREADY_EXISTS, then fail
  187. if (ERROR_ALREADY_EXISTS != dwLastError && ERROR_FILE_EXISTS != dwLastError)
  188. {
  189. hr = TrapError(E_FAIL);
  190. goto exit;
  191. }
  192. // Increment cUnique
  193. cUnique++;
  194. // Format szUnique
  195. wnsprintf(szUnique, ARRAYSIZE(szUnique), "%d", cUnique);
  196. }
  197. exit:
  198. // Cleanup
  199. if (INVALID_HANDLE_VALUE != hTemp)
  200. CloseHandle(hTemp);
  201. // Done
  202. return hr;
  203. }
  204. // --------------------------------------------------------------------------------
  205. // CreateTempFile
  206. // --------------------------------------------------------------------------------
  207. OESTDAPI_(HRESULT) CreateTempFile(LPCSTR pszSuggest, LPCSTR pszExtension, LPSTR *ppszFilePath, HANDLE *phFile)
  208. {
  209. // Locals
  210. HRESULT hr=S_OK;
  211. CHAR szTempDir[MAX_PATH];
  212. WCHAR wszTempDir[MAX_PATH];
  213. CHAR szFileName[MAX_PATH];
  214. LPSTR pszFilePath=NULL;
  215. LPSTR pszFile;
  216. LPSTR pszExt;
  217. ULONG cbAlloc;
  218. // Invalid Arg
  219. Assert(ppszFilePath && phFile);
  220. // Init
  221. *phFile = INVALID_HANDLE_VALUE;
  222. // Create a temp file stream in URL cache
  223. if(AthGetTempUniquePathW(ARRAYSIZE(wszTempDir), wszTempDir))
  224. {
  225. LPSTR pszAnsiStr = PszToANSI(CP_ACP, wszTempDir);
  226. if (!pszAnsiStr)
  227. goto exit;
  228. StrCpyN(szTempDir, pszAnsiStr, ARRAYSIZE(szTempDir));
  229. MemFree(pszAnsiStr);
  230. }
  231. // If cannot find URL cache try TEMP dir
  232. else
  233. {
  234. DWORD nBufferLength = GetTempPath(ARRAYSIZE(szTempDir), szTempDir);
  235. if (nBufferLength == 0 || nBufferLength > ARRAYSIZE(szTempDir))
  236. {
  237. hr = TrapError(E_FAIL);
  238. goto exit;
  239. }
  240. }
  241. // Compute Max Size of pszFilePath
  242. cbAlloc = MAX_PATH + lstrlen(szTempDir);
  243. if (pszSuggest)
  244. cbAlloc += lstrlen(pszSuggest);
  245. if (pszExtension)
  246. cbAlloc += lstrlen(pszExtension);
  247. // Allocate m_pszNeedFile
  248. CHECKALLOC(pszFilePath = PszAllocA(cbAlloc + 1));
  249. // Create a unique file path with suggested pszFileName and pszExtension
  250. if (NULL != pszSuggest)
  251. {
  252. // Find the filename
  253. pszFile = PathFindFileName(pszSuggest);
  254. // Get the Extension
  255. pszExt = PathFindExtension(pszSuggest);
  256. // If no pszExtension, use extension from pszSuggest
  257. if (NULL == pszExtension)
  258. pszExtension = pszExt ? pszExt : (LPSTR)c_szDotDat;
  259. // Copy fileName
  260. if (pszExt && pszFile && pszExt >= pszFile)
  261. StrCpyN(szFileName, pszFile, (DWORD) (min((pszExt - pszFile) - 1, ARRAYSIZE(szFileName))));
  262. else
  263. StrCpyN(szFileName, pszSuggest, ARRAYSIZE(szFileName));
  264. // Fixup szTempDir
  265. if (szTempDir[lstrlen(szTempDir) - 1] != '\\')
  266. StrCatBuff(szTempDir, "\\", ARRAYSIZE(szTempDir));
  267. // GenerateUniqueFileName
  268. hr = GenerateUniqueFileName(szTempDir, szFileName, pszExtension, pszFilePath, cbAlloc);
  269. }
  270. // If no filename and no extension or suggested name failed, just use the windows function
  271. if ((NULL == pszSuggest) || FAILED(hr))
  272. {
  273. hr = S_OK;
  274. // Get Temp File Name
  275. if (0 == GetTempFileName(szTempDir, "wbk", 0, pszFilePath))
  276. {
  277. hr = TrapError(E_FAIL);
  278. goto exit;
  279. }
  280. }
  281. // Open the File
  282. *phFile = CreateFile(pszFilePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL , NULL);
  283. if (INVALID_HANDLE_VALUE == *phFile)
  284. {
  285. hr = TrapError(E_FAIL);
  286. goto exit;
  287. }
  288. // SetReturn
  289. *ppszFilePath = pszFilePath;
  290. pszFilePath = NULL;
  291. exit:
  292. // Cleanup
  293. SafeMemFree(pszFilePath);
  294. // Done
  295. return hr;
  296. }
  297. // --------------------------------------------------------------------------------
  298. // WriteStreamToFileHandle
  299. // --------------------------------------------------------------------------------
  300. OESTDAPI_(HRESULT) WriteStreamToFileHandle(IStream *pStream, HANDLE hFile, ULONG *pcbTotal)
  301. {
  302. // Locals
  303. HRESULT hr=S_OK;
  304. ULONG cbRead;
  305. ULONG cbTotal=0;
  306. BYTE rgbBuffer[2048];
  307. ULONG cbWrote;
  308. // Invalid Arg
  309. if(!pStream || !hFile || (hFile == INVALID_HANDLE_VALUE))
  310. {
  311. Assert(FALSE);
  312. return(E_INVALIDARG);
  313. }
  314. // Dump pStream to hFile
  315. while(1)
  316. {
  317. // Read a blob
  318. CHECKHR(hr = pStream->Read(rgbBuffer, sizeof(rgbBuffer), &cbRead));
  319. // Done
  320. if (0 == cbRead)
  321. break;
  322. // Write to the file
  323. if (0 == WriteFile(hFile, rgbBuffer, cbRead, &cbWrote, NULL))
  324. {
  325. hr = TrapError(E_FAIL);
  326. goto exit;
  327. }
  328. // Count Bytes
  329. cbTotal += cbWrote;
  330. }
  331. // Return Total
  332. if (pcbTotal)
  333. *pcbTotal = cbTotal;
  334. exit:
  335. // Done
  336. return hr;
  337. }
  338. // --------------------------------------------------------------------------------
  339. // DeleteTempFile
  340. // --------------------------------------------------------------------------------
  341. OESTDAPI_(HRESULT) DeleteTempFile(LPTEMPFILEINFO pTempFile)
  342. {
  343. // Locals
  344. BOOL fDeleted;
  345. DWORD dwAttributes;
  346. // If NULL, assume the file has been deleted
  347. if (NULL == pTempFile->pszFilePath)
  348. return S_OK;
  349. // Have we launched a process on this temp file which is still running?
  350. if (pTempFile->hProcess && WAIT_OBJECT_0 != WaitForSingleObject(pTempFile->hProcess, 0))
  351. return S_FALSE; // This file is probably still in use: won't delete
  352. // First check if this is a file or a directory, then terminate it
  353. dwAttributes = GetFileAttributes(pTempFile->pszFilePath);
  354. if (0xFFFFFFFF != dwAttributes && (FILE_ATTRIBUTE_DIRECTORY & dwAttributes))
  355. fDeleted = RemoveDirectory(pTempFile->pszFilePath);
  356. else
  357. fDeleted = DeleteFile(pTempFile->pszFilePath);
  358. // Done
  359. return fDeleted ? S_OK : S_FALSE;
  360. }
  361. // --------------------------------------------------------------------------------
  362. // AppendTempFileList
  363. // --------------------------------------------------------------------------------
  364. OESTDAPI_(HRESULT) AppendTempFileList(LPTEMPFILEINFO *ppHead, LPSTR pszFilePath, HANDLE hProcess)
  365. {
  366. // Locals
  367. HRESULT hr=S_OK;
  368. LPTEMPFILEINFO pTempFile, pInsertionPt;
  369. // Allocate pTempFile
  370. CHECKALLOC(pTempFile = (LPTEMPFILEINFO)g_pMalloc->Alloc(sizeof(TEMPFILEINFO)));
  371. // Fill in the fields
  372. ZeroMemory(pTempFile, sizeof(TEMPFILEINFO));
  373. pTempFile->pszFilePath = pszFilePath;
  374. pTempFile->hProcess = hProcess;
  375. pTempFile->pNext = NULL;
  376. // Insert new record at the end of the linked list
  377. pInsertionPt = *ppHead;
  378. if (NULL == pInsertionPt)
  379. // Insert record into empty linked list
  380. (*ppHead) = pTempFile;
  381. else
  382. {
  383. // Insert record at end of linked list
  384. while (NULL != pInsertionPt->pNext)
  385. pInsertionPt = pInsertionPt->pNext;
  386. pInsertionPt->pNext = pTempFile;
  387. }
  388. exit:
  389. // Done
  390. return hr;
  391. }
  392. // --------------------------------------------------------------------------------
  393. // DeleteTempFileOnShutdown
  394. // --------------------------------------------------------------------------------
  395. OESTDAPI_(VOID) DeleteTempFileOnShutdown(LPTEMPFILEINFO pTempFile)
  396. {
  397. LPTEMPFILEINFO pInsertionPt;
  398. Assert(NULL != pTempFile && NULL == pTempFile->pNext);
  399. // Enter global Critical Section
  400. EnterCriticalSection(&g_csTempFileList);
  401. // Insert new record at the end of the global linked list
  402. pTempFile->pNext = NULL;
  403. pInsertionPt = g_pTempFileHead;
  404. if (NULL == pInsertionPt)
  405. // Insert record into empty linked list
  406. g_pTempFileHead = pTempFile;
  407. else
  408. {
  409. // Insert record at end of linked list
  410. while (NULL != pInsertionPt->pNext)
  411. pInsertionPt = pInsertionPt->pNext;
  412. pInsertionPt->pNext = pTempFile;
  413. }
  414. // Leave global Critical Section
  415. LeaveCriticalSection(&g_csTempFileList);
  416. }
  417. // --------------------------------------------------------------------------------
  418. // DeleteTempFileOnShutdownEx
  419. // --------------------------------------------------------------------------------
  420. OESTDAPI_(VOID) DeleteTempFileOnShutdownEx(LPSTR pszFilePath, HANDLE hProcess)
  421. {
  422. // Enter global Critical Section
  423. EnterCriticalSection(&g_csTempFileList);
  424. // Append to globa list
  425. AppendTempFileList(&g_pTempFileHead, pszFilePath, hProcess);
  426. // Enter global Critical Section
  427. LeaveCriticalSection(&g_csTempFileList);
  428. }
  429. // --------------------------------------------------------------------------------
  430. // CleanupGlobalTempFiles
  431. // --------------------------------------------------------------------------------
  432. OESTDAPI_(VOID) CleanupGlobalTempFiles(void)
  433. {
  434. // Locals
  435. LPTEMPFILEINFO pCurrent;
  436. LPTEMPFILEINFO pNext;
  437. // Enter global Critical Section
  438. EnterCriticalSection(&g_csTempFileList);
  439. // Init
  440. pCurrent = g_pTempFileHead;
  441. // Do the loop
  442. while(pCurrent)
  443. {
  444. // Save Next
  445. pNext = pCurrent->pNext;
  446. // Delete the temp file
  447. DeleteTempFile(pCurrent);
  448. // Free file name
  449. SafeMemFree(pCurrent->pszFilePath);
  450. // Free pCurrent
  451. g_pMalloc->Free(pCurrent);
  452. // Goto Next
  453. pCurrent = pNext;
  454. }
  455. // Null the head
  456. g_pTempFileHead = NULL;
  457. // Leave global Critical Section
  458. LeaveCriticalSection(&g_csTempFileList);
  459. }
  460. // QFE 2522
  461. #define EXT_SIZE 4
  462. #define TMP_SIZE 10
  463. // =====================================================================================
  464. // FBuildTempPath
  465. // =====================================================================================
  466. BOOL FBuildTempPath(LPTSTR lpszOrigFile, LPTSTR lpszPath, ULONG cbMaxPath, BOOL fLink)
  467. {
  468. LPWSTR lpszOrigFileW = PszToUnicode(CP_ACP, lpszOrigFile);
  469. LPWSTR lpszPathW = NULL;
  470. BOOL result = FALSE;
  471. if (!lpszOrigFileW)
  472. return result;
  473. MemAlloc((LPVOID *) &lpszPathW, sizeof(WCHAR) * cbMaxPath);
  474. if (lpszPathW)
  475. {
  476. result = FBuildTempPathW(lpszOrigFileW, lpszPathW, cbMaxPath, fLink);
  477. if (result)
  478. WideCharToMultiByte(CP_ACP, 0, lpszPathW, -1, lpszPath, cbMaxPath, NULL, NULL);
  479. }
  480. MemFree(lpszOrigFileW);
  481. MemFree(lpszPathW);
  482. return result;
  483. }
  484. BOOL FBuildTempPathW(LPWSTR lpszOrigFile, LPWSTR lpszPath, ULONG cchMaxPath, BOOL fLink)
  485. {
  486. // Locals
  487. INT i;
  488. WCHAR *pszName,
  489. *pszExt,
  490. *pszOrigFileTemp = NULL,
  491. szName[MAX_PATH],
  492. szTempDir[MAX_PATH];
  493. // Check Params
  494. AssertSz(lpszOrigFile && lpszPath, "Null Parameter");
  495. // Get Temp Path
  496. if(!AthGetTempUniquePathW(ARRAYSIZE(szTempDir), szTempDir))
  497. szTempDir[0] = L'\0';
  498. int nTmp = lstrlenW(szTempDir);
  499. if(nTmp >= (((int) cchMaxPath) - TMP_SIZE - EXT_SIZE - 1))
  500. {
  501. StrCpyNW(szTempDir, L"\\", ARRAYSIZE(szTempDir));
  502. nTmp = lstrlenW(szTempDir);
  503. }
  504. DWORD cchSize = (lstrlenW(lpszOrigFile) + 1);
  505. if (!MemAlloc((LPVOID *) &pszOrigFileTemp, sizeof(WCHAR) * cchSize) ||
  506. (lpszOrigFile == NULL))
  507. return(FALSE);
  508. StrCpyNW(pszOrigFileTemp, lpszOrigFile, cchSize);
  509. // Get the file name and extension
  510. pszName = PathFindFileNameW(pszOrigFileTemp);
  511. Assert(!FIsEmptyW(pszName));
  512. pszExt = PathFindExtensionW(pszOrigFileTemp);
  513. if(nTmp + lstrlenW(pszName) + lstrlenW(pszExt)> (((int) cchMaxPath) - TMP_SIZE)) // QFE 2522
  514. {
  515. if(nTmp + lstrlenW(pszExt) > (((int) cchMaxPath) - TMP_SIZE))
  516. pszExt[0] = L'\0';
  517. // Truncate anything that won't fit in the buffer passed in
  518. if(lstrlenW(pszName) >= ((int) cchMaxPath) - (nTmp + lstrlenW(pszExt) + TMP_SIZE + 1))
  519. *(pszName + ((int) cchMaxPath) - (nTmp + lstrlenW(pszExt) + TMP_SIZE + 1)) = '\0';
  520. }
  521. if (*pszExt != 0)
  522. {
  523. Assert(*pszExt == L'.');
  524. *pszExt = 0;
  525. StrCpyNW(szName, pszName, ARRAYSIZE(szName));
  526. *pszExt = L'.';
  527. }
  528. else
  529. {
  530. StrCpyNW(szName, pszName, ARRAYSIZE(szName));
  531. }
  532. if (fLink)
  533. pszExt = (LPWSTR)c_szLnkExt;
  534. // Make first attemp file name
  535. Assert (szTempDir[lstrlenW(szTempDir)-1] == L'\\');
  536. Assert(cchMaxPath >= (ULONG)(lstrlenW(szTempDir) + lstrlenW(szName) + lstrlenW(pszExt) + TMP_SIZE));
  537. StrCpyNW(lpszPath, szTempDir, cchMaxPath);
  538. StrCatBuffW(lpszPath, szName, cchMaxPath);
  539. StrCatBuffW(lpszPath, pszExt, cchMaxPath);
  540. // If it doesn't exist, were done
  541. if (PathFileExistsW(lpszPath) == FALSE)
  542. {
  543. MemFree(pszOrigFileTemp);
  544. return(TRUE);
  545. }
  546. // Loop to find a temp name that doesn't exist
  547. for (i=1; i<100 ;i++)
  548. {
  549. // Build new path
  550. wnsprintfW(lpszPath, cchMaxPath, L"%s%s (%d)%s", szTempDir, szName, i, pszExt);
  551. // If it doesn't exist, were done
  552. if (PathFileExistsW(lpszPath) == FALSE)
  553. {
  554. MemFree(pszOrigFileTemp);
  555. return(TRUE);
  556. }
  557. }
  558. // Done
  559. MemFree(pszOrigFileTemp);
  560. return(FALSE);
  561. }
  562. void FreeTempFileList(LPTEMPFILEINFO pTempFileHead)
  563. {
  564. // Locals
  565. LPTEMPFILEINFO pCurrent;
  566. LPTEMPFILEINFO pNext;
  567. // Init
  568. pCurrent = pTempFileHead;
  569. // Do the loop
  570. while(pCurrent)
  571. {
  572. // Save Next
  573. pNext = pCurrent->pNext;
  574. // If not deleted, append to global file list
  575. if (S_FALSE == DeleteTempFile(pCurrent))
  576. {
  577. // MSOERT maintains a list of global temp files to be killed on shutdown
  578. DeleteTempFileOnShutdown(pCurrent);
  579. }
  580. // Otherwise, delete this node
  581. else
  582. {
  583. // Free file name
  584. SafeMemFree(pCurrent->pszFilePath);
  585. // Free pCurrent
  586. g_pMalloc->Free(pCurrent);
  587. }
  588. // Goto Next
  589. pCurrent = pNext;
  590. }
  591. }
  592. DWORD CALLBACK EditStreamInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb)
  593. {
  594. AssertSz(dwCookie, "Houston, we have a problem...");
  595. ((LPSTREAM)dwCookie)->Read(pbBuff, cb, (ULONG *)pcb);
  596. #ifdef DEBUG
  597. // validate for the richedit bug...
  598. // if we put a \r in the richedit as the last char without a \n
  599. // ie not a \r\n pair, it bithces and faults...
  600. if(*pcb && *pcb<cb)
  601. AssertSz(pbBuff[(*pcb)-1]!='\r', "is this the richedit bug??");
  602. #endif
  603. return NOERROR;
  604. }
  605. DWORD CALLBACK EditStreamOutCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb)
  606. {
  607. return ((LPSTREAM)dwCookie)->Write(pbBuff, cb, (ULONG *)pcb);
  608. }
  609. HRESULT RicheditStreamIn(HWND hwndRE, LPSTREAM pstm, ULONG uSelFlags)
  610. {
  611. EDITSTREAM es;
  612. if(!pstm)
  613. return E_INVALIDARG;
  614. if(!IsWindow(hwndRE))
  615. return E_INVALIDARG;
  616. HrRewindStream(pstm);
  617. es.dwCookie = (DWORD_PTR)pstm;
  618. es.pfnCallback=(EDITSTREAMCALLBACK)EditStreamInCallback;
  619. SendMessage(hwndRE, EM_STREAMIN, uSelFlags, (LPARAM)&es);
  620. return NOERROR;
  621. }
  622. HRESULT RicheditStreamOut(HWND hwndRE, LPSTREAM pstm, ULONG uSelFlags)
  623. {
  624. EDITSTREAM es;
  625. if(!pstm)
  626. return E_INVALIDARG;
  627. if(!IsWindow(hwndRE))
  628. return E_INVALIDARG;
  629. es.dwCookie = (DWORD_PTR)pstm;
  630. es.pfnCallback=(EDITSTREAMCALLBACK)EditStreamOutCallback;
  631. SendMessage(hwndRE, EM_STREAMOUT, uSelFlags, (LPARAM)&es);
  632. return NOERROR;
  633. }
  634. HRESULT ShellUtil_GetSpecialFolderPath(DWORD dwSpecialFolder, LPSTR rgchPath)
  635. {
  636. LPITEMIDLIST pidl = NULL;
  637. HRESULT hr = E_FAIL;
  638. if (SHGetSpecialFolderLocation(NULL, dwSpecialFolder, &pidl)==S_OK)
  639. {
  640. if (SHGetPathFromIDList(pidl, rgchPath))
  641. hr = S_OK;
  642. SHFree(pidl);
  643. }
  644. return hr;
  645. }
  646. /*
  647. * CenterDialog
  648. *
  649. * Purpose:
  650. * This function centers a dialog with respect to its parent
  651. * dialog.
  652. *
  653. * Parameters:
  654. * hwndDlg hwnd of the dialog to center
  655. */
  656. VOID CenterDialog(HWND hwndDlg)
  657. {
  658. HWND hwndOwner;
  659. RECT rc;
  660. RECT rcDlg;
  661. RECT rcOwner;
  662. RECT rcWork;
  663. INT x;
  664. INT y;
  665. INT nAdjust;
  666. // Get the working area rectangle
  667. SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
  668. // Get the owner window and dialog box rectangles.
  669. // The window rect of the destop window is in trouble on multimonitored
  670. // macs. GetWindow only gets the main screen.
  671. if (hwndOwner = GetParent(hwndDlg))
  672. GetWindowRect(hwndOwner, &rcOwner);
  673. else
  674. rcOwner = rcWork;
  675. GetWindowRect(hwndDlg, &rcDlg);
  676. rc = rcOwner;
  677. // Offset the owner and dialog box rectangles so that
  678. // right and bottom values represent the width and
  679. // height, and then offset the owner again to discard
  680. // space taken up by the dialog box.
  681. OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
  682. OffsetRect(&rc, -rc.left, -rc.top);
  683. OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
  684. // The new position is the sum of half the remaining
  685. // space and the owner's original position.
  686. // But not less than Zero - jefbai
  687. x= rcOwner.left + (rc.right / 2);
  688. y= rcOwner.top + (rc.bottom / 2);
  689. // Make sure the dialog doesn't go off the right edge of the screen
  690. nAdjust = rcWork.right - (x + rcDlg.right);
  691. if (nAdjust < 0)
  692. x += nAdjust;
  693. //$ Raid 5128: Make sure the left edge is visible
  694. if (x < rcWork.left)
  695. x = rcWork.left;
  696. // Make sure the dialog doesn't go off the bottom edge of the screen
  697. nAdjust = rcWork.bottom - (y + rcDlg.bottom);
  698. if (nAdjust < 0)
  699. y += nAdjust;
  700. //$ Raid 5128: Make sure the top edge is visible
  701. if (y < rcWork.top)
  702. y = rcWork.top;
  703. SetWindowPos(hwndDlg, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  704. }
  705. void SetIntlFont(HWND hwnd)
  706. {
  707. HFONT hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  708. if (hfont == NULL)
  709. hfont = (HFONT)GetStockObject(SYSTEM_FONT);
  710. if (hfont != NULL)
  711. SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
  712. }
  713. // See whether entire string will fit in *prc; if not, compute number of chars
  714. // that will fit, including ellipses. Returns length of string in *pcchDraw.
  715. //
  716. BOOL NeedsEllipses(HDC hdc, LPCTSTR pszText, RECT FAR* prc, int FAR* pcchDraw, int cxEllipses)
  717. {
  718. int cchText;
  719. int cxRect;
  720. int ichMin, ichMax, ichMid;
  721. SIZE siz;
  722. #if !defined(UNICODE) // && defined(DBCS)
  723. LPCTSTR lpsz;
  724. #endif
  725. cxRect = prc->right - prc->left;
  726. cchText = lstrlen(pszText);
  727. if (cchText == 0)
  728. {
  729. *pcchDraw = cchText;
  730. return FALSE;
  731. }
  732. GetTextExtentPoint32(hdc, pszText, cchText, &siz);
  733. if (siz.cx <= cxRect)
  734. {
  735. *pcchDraw = cchText;
  736. return FALSE;
  737. }
  738. cxRect -= cxEllipses;
  739. // If no room for ellipses, always show first character.
  740. //
  741. ichMax = 1;
  742. if (cxRect > 0)
  743. {
  744. // Binary search to find character that will fit
  745. ichMin = 0;
  746. ichMax = cchText;
  747. while (ichMin < ichMax)
  748. {
  749. // Be sure to round up, to make sure we make progress in
  750. // the loop if ichMax == ichMin + 1.
  751. //
  752. ichMid = (ichMin + ichMax + 1) / 2;
  753. GetTextExtentPoint32(hdc, &pszText[ichMin], ichMid - ichMin, &siz);
  754. if (siz.cx < cxRect)
  755. {
  756. ichMin = ichMid;
  757. cxRect -= siz.cx;
  758. }
  759. else if (siz.cx > cxRect)
  760. {
  761. ichMax = ichMid - 1;
  762. }
  763. else
  764. {
  765. // Exact match up up to ichMid: just exit.
  766. //
  767. ichMax = ichMid;
  768. break;
  769. }
  770. }
  771. // Make sure we always show at least the first character...
  772. //
  773. if (ichMax < 1)
  774. ichMax = 1;
  775. }
  776. #if !defined(UNICODE) // && defined(DBCS)
  777. // b#8934
  778. lpsz = &pszText[ichMax];
  779. while ( lpsz-- > pszText )
  780. {
  781. if (!IsDBCSLeadByte(*lpsz))
  782. break;
  783. }
  784. ichMax += ( (&pszText[ichMax] - lpsz) & 1 ) ? 0: 1;
  785. #endif
  786. *pcchDraw = ichMax;
  787. return TRUE;
  788. }
  789. #define CCHELLIPSES 3
  790. #define CCHLABELMAX MAX_PATH
  791. void IDrawText(HDC hdc, LPCTSTR pszText, RECT FAR* prc, BOOL fEllipses, int cyChar)
  792. {
  793. int cchText,
  794. cxEllipses;
  795. RECT rc;
  796. TCHAR ach[CCHLABELMAX + CCHELLIPSES];
  797. SIZE sze;
  798. // REVIEW: Performance idea:
  799. // We could cache the currently selected text color
  800. // so we don't have to set and restore it each time
  801. // when the color is the same.
  802. //
  803. if (!pszText)
  804. return;
  805. if (IsRectEmpty(prc))
  806. return;
  807. rc = *prc;
  808. if(fEllipses)
  809. {
  810. GetTextExtentPoint32(hdc, g_szEllipsis, lstrlen(g_szEllipsis), &sze);
  811. cxEllipses=sze.cx;
  812. }
  813. if ((fEllipses) &&
  814. NeedsEllipses(hdc, pszText, &rc, &cchText, cxEllipses))
  815. {
  816. // In some cases cchText was comming back bigger than
  817. // ARRYASIZE(ach), so we need to make sure we don't overflow the buffer
  818. // if cchText is too big for the buffer, truncate it down to size
  819. if (cchText >= ARRAYSIZE(ach) - CCHELLIPSES)
  820. cchText = ARRAYSIZE(ach) - CCHELLIPSES - 1;
  821. memcpy(ach, pszText, cchText * sizeof(TCHAR));
  822. StrCpyN(ach + cchText, g_szEllipsis, (ARRAYSIZE(ach) - cchText));
  823. pszText = ach;
  824. cchText += CCHELLIPSES;
  825. }
  826. else
  827. {
  828. cchText = lstrlen(pszText);
  829. }
  830. // Center vertically in case the bitmap (to the left) is larger than
  831. // the height of one line
  832. if (cyChar)
  833. rc.top += (rc.bottom - rc.top - cyChar) / 2;
  834. ExtTextOut(hdc, rc.left, rc.top, 0, prc, pszText, cchText, NULL);
  835. }
  836. BOOL FIsHTMLFile(LPSTR pszFile)
  837. {
  838. int cch;
  839. if(pszFile==NULL)
  840. return FALSE;
  841. cch = lstrlen(pszFile);
  842. if ((cch > 4 && lstrcmpi(&pszFile[cch-4], ".htm")==0) ||
  843. (cch > 5 && lstrcmpi(&pszFile[cch-5], ".html")==0))
  844. return TRUE;
  845. return FALSE;
  846. }
  847. BOOL FIsHTMLFileW(LPWSTR pwszFile)
  848. {
  849. int cch;
  850. if(pwszFile==NULL)
  851. return FALSE;
  852. cch = lstrlenW(pwszFile);
  853. if ((cch > 4 && StrCmpIW(&pwszFile[cch-4], L".htm")==0) ||
  854. (cch > 5 && StrCmpIW(&pwszFile[cch-5], L".html")==0))
  855. return TRUE;
  856. return FALSE;
  857. }
  858. BOOL GetExePath(LPCTSTR szExe, TCHAR *szPath, DWORD cch, BOOL fDirOnly)
  859. {
  860. BOOL fRet;
  861. HKEY hkey;
  862. DWORD dwType, cb;
  863. TCHAR sz[MAX_PATH], szT[MAX_PATH];
  864. Assert(szExe != NULL);
  865. Assert(szPath != NULL);
  866. fRet = FALSE;
  867. wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, c_szAppPaths, szExe);
  868. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz, 0, KEY_QUERY_VALUE, &hkey))
  869. {
  870. cb = sizeof(szT);
  871. if (ERROR_SUCCESS == RegQueryValueEx(hkey, fDirOnly ? c_szRegPath : NULL, 0, &dwType, (LPBYTE)szT, &cb) && cb)
  872. {
  873. if (dwType == REG_EXPAND_SZ)
  874. {
  875. cb = ExpandEnvironmentStrings(szT, szPath, cch);
  876. if (cb != 0 && cb <= cch)
  877. fRet = TRUE;
  878. }
  879. else
  880. {
  881. Assert(dwType == REG_SZ);
  882. StrCpyN(szPath, szT, cch);
  883. fRet = TRUE;
  884. }
  885. }
  886. RegCloseKey(hkey);
  887. }
  888. return(fRet);
  889. }
  890. int MessageBoxInstW(HINSTANCE hInst, HWND hwndOwner, LPWSTR pwszTitle, LPWSTR pwsz1, LPWSTR pwsz2, UINT fuStyle,
  891. PFLOADSTRINGW pfLoadStringW, PFMESSAGEBOXW pfMessageBoxW)
  892. {
  893. WCHAR wszTitle[CCHMAX_STRINGRES];
  894. WCHAR wszText[2 * CCHMAX_STRINGRES + 2];
  895. int cch;
  896. Assert(pwsz1);
  897. Assert(pwszTitle != NULL);
  898. if (!(fuStyle & MB_ICONEXCLAMATION) &&
  899. !(fuStyle & MB_ICONWARNING) &&
  900. !(fuStyle & MB_ICONINFORMATION) &&
  901. !(fuStyle & MB_ICONASTERISK) &&
  902. //!(fuStyle & MB_ICONQUESTION) && // BUG: 18105
  903. !(fuStyle & MB_ICONSTOP) &&
  904. !(fuStyle & MB_ICONERROR) &&
  905. !(fuStyle & MB_ICONHAND))
  906. {
  907. if (fuStyle & MB_OK)
  908. fuStyle |= MB_ICONINFORMATION;
  909. else if (fuStyle & MB_YESNO || fuStyle & MB_YESNOCANCEL || fuStyle & MB_OKCANCEL)
  910. fuStyle |= MB_ICONEXCLAMATION; // BUG 18105 MB_ICONQUESTION;
  911. else if (fuStyle & MB_RETRYCANCEL || fuStyle & MB_ABORTRETRYIGNORE)
  912. fuStyle |= MB_ICONWARNING;
  913. else
  914. fuStyle |= MB_ICONWARNING;
  915. }
  916. if (IS_INTRESOURCE(pwszTitle))
  917. {
  918. // its a string resource id
  919. cch = pfLoadStringW(hInst, PtrToUlong(pwszTitle), wszTitle, ARRAYSIZE(wszTitle));
  920. if (cch == 0)
  921. return(0);
  922. pwszTitle = wszTitle;
  923. }
  924. if (!(IS_INTRESOURCE(pwsz1)))
  925. {
  926. // its a pointer to a string
  927. Assert(lstrlenW(pwsz1) < CCHMAX_STRINGRES);
  928. if (NULL == StrCpyNW(wszText, pwsz1, ARRAYSIZE(wszText)))
  929. return(0);
  930. cch = lstrlenW(wszText);
  931. }
  932. else
  933. {
  934. // its a string resource id
  935. cch = pfLoadStringW(hInst, PtrToUlong(pwsz1), wszText, ARRAYSIZE(wszText)-2);
  936. if (cch == 0)
  937. return(0);
  938. }
  939. if (pwsz2)
  940. {
  941. // there's another string that we need to append to the
  942. // first string...
  943. wszText[cch++] = L'\n';
  944. wszText[cch++] = L'\n';
  945. if (!(IS_INTRESOURCE(pwsz2)))
  946. {
  947. // its a pointer to a string
  948. Assert(lstrlenW(pwsz2) < CCHMAX_STRINGRES);
  949. if (NULL == StrCpyNW(&wszText[cch], pwsz2, (ARRAYSIZE(wszText) - cch)))
  950. return(0);
  951. }
  952. else
  953. {
  954. int cchTemp = ARRAYSIZE(wszText) - cch;
  955. Assert(cchTemp > 0);
  956. if (0 == pfLoadStringW(hInst, PtrToUlong(pwsz2), &wszText[cch], cchTemp))
  957. return(0);
  958. }
  959. }
  960. return(pfMessageBoxW(hwndOwner, wszText, pwszTitle, MB_SETFOREGROUND | fuStyle));
  961. }
  962. int MessageBoxInst(HINSTANCE hInst, HWND hwndOwner, LPTSTR pszTitle, LPTSTR psz1, LPTSTR psz2, UINT fuStyle)
  963. {
  964. TCHAR szTitle[CCHMAX_STRINGRES];
  965. TCHAR szText[2 * CCHMAX_STRINGRES + 2];
  966. int cch;
  967. Assert(psz1);
  968. Assert(pszTitle != NULL);
  969. if (!(fuStyle & MB_ICONEXCLAMATION) &&
  970. !(fuStyle & MB_ICONWARNING) &&
  971. !(fuStyle & MB_ICONINFORMATION) &&
  972. !(fuStyle & MB_ICONASTERISK) &&
  973. //!(fuStyle & MB_ICONQUESTION) && // BUG: 18105
  974. !(fuStyle & MB_ICONSTOP) &&
  975. !(fuStyle & MB_ICONERROR) &&
  976. !(fuStyle & MB_ICONHAND))
  977. {
  978. if (fuStyle & MB_OK)
  979. fuStyle |= MB_ICONINFORMATION;
  980. else if (fuStyle & MB_YESNO || fuStyle & MB_YESNOCANCEL || fuStyle & MB_OKCANCEL)
  981. fuStyle |= MB_ICONEXCLAMATION; // BUG 18105 MB_ICONQUESTION;
  982. else if (fuStyle & MB_RETRYCANCEL || fuStyle & MB_ABORTRETRYIGNORE)
  983. fuStyle |= MB_ICONWARNING;
  984. else
  985. fuStyle |= MB_ICONWARNING;
  986. }
  987. if (IS_INTRESOURCE(pszTitle))
  988. {
  989. // its a string resource id
  990. cch = LoadString(hInst, PtrToUlong(pszTitle), szTitle, ARRAYSIZE(szTitle));
  991. if (cch == 0)
  992. return(0);
  993. pszTitle = szTitle;
  994. }
  995. if (!(IS_INTRESOURCE(psz1)))
  996. {
  997. // its a pointer to a string
  998. // Assert(lstrlen(psz1) < CCHMAX_STRINGRES);
  999. // if (NULL == StrCpyN(szText, psz1, ARRAYSIZE(szText)))
  1000. // return(0);
  1001. if (NULL == StrCpyN(szText, psz1, ARRAYSIZE(szText) - 1))
  1002. return(0);
  1003. szText[ARRAYSIZE(szText) - 1] = '\0';
  1004. cch = lstrlen(szText);
  1005. }
  1006. else
  1007. {
  1008. // its a string resource id
  1009. cch = LoadString(hInst, PtrToUlong(psz1), szText, ARRAYSIZE(szText)-1);
  1010. if (cch == 0)
  1011. return(0);
  1012. }
  1013. // check that we have enough room for the '\n's and at least one byte of data
  1014. if (psz2 && (cch < (ARRAYSIZE(szText) - 4)))
  1015. {
  1016. // there's another string that we need to append to the
  1017. // first string...
  1018. szText[cch++] = '\n';
  1019. szText[cch++] = '\n';
  1020. if (!(IS_INTRESOURCE(psz2)))
  1021. {
  1022. // its a pointer to a string
  1023. // Assert(lstrlen(psz2) < CCHMAX_STRINGRES);
  1024. if (NULL == StrCpyN(&szText[cch], psz2, (ARRAYSIZE(szText)-1)-cch))
  1025. return(0);
  1026. }
  1027. else
  1028. {
  1029. int cchTemp = ARRAYSIZE(szText) - cch;
  1030. Assert(cchTemp > 0);
  1031. if (0 == LoadString(hInst, PtrToUlong(psz2), &szText[cch], cchTemp))
  1032. return(0);
  1033. }
  1034. }
  1035. return(MessageBox(hwndOwner, szText, pszTitle, MB_SETFOREGROUND | fuStyle));
  1036. }
  1037. BOOL BrowseForFolder(HINSTANCE hInst, HWND hwnd, TCHAR *pszDir, int cch, int idsText, BOOL fFileSysOnly)
  1038. {
  1039. LPITEMIDLIST plist;
  1040. BROWSEINFO bi;
  1041. BROWSEFOLDERINFOA bfi;
  1042. BOOL fRet = FALSE;
  1043. CHAR *psz = NULL,
  1044. szTemp[MAX_PATH];
  1045. CHAR szRes[256];
  1046. Assert(pszDir != NULL);
  1047. Assert(cch >= MAX_PATH);
  1048. LoadString(hInst, idsText, szRes, ARRAYSIZE(szRes));
  1049. bfi.psz = pszDir;
  1050. bfi.fFileSysOnly = fFileSysOnly;
  1051. bi.hwndOwner = hwnd;
  1052. bi.pidlRoot = NULL;
  1053. bi.pszDisplayName = szTemp;
  1054. bi.lpszTitle = szRes;
  1055. bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
  1056. bi.lpfn = BrowseCallbackProcA;
  1057. bi.lParam = (LPARAM)&bfi;
  1058. plist = SHBrowseForFolder(&bi);
  1059. if (plist != NULL)
  1060. {
  1061. fRet = SHGetPathFromIDList(plist, pszDir);
  1062. SHFree(plist);
  1063. }
  1064. return(fRet);
  1065. }
  1066. BOOL SHGetPathFromIDListAthW(LPCITEMIDLIST pidl, LPWSTR pwszPath)
  1067. {
  1068. CHAR pszPath[MAX_PATH];
  1069. BOOL fSucceeded = FALSE;
  1070. fSucceeded = SHGetPathFromIDListW(pidl, pwszPath);
  1071. if (!fSucceeded)
  1072. {
  1073. fSucceeded = SHGetPathFromIDListA(pidl, pszPath);
  1074. if (fSucceeded)
  1075. fSucceeded = (0 != MultiByteToWideChar(CP_ACP, 0, pszPath, -1, pwszPath, MAX_PATH));
  1076. }
  1077. return fSucceeded;
  1078. }
  1079. LPITEMIDLIST SHBrowseForFolderAthW(LPBROWSEINFOW pbiW)
  1080. {
  1081. LPITEMIDLIST pidl = NULL;
  1082. LPSTR pszTitle = NULL;
  1083. CHAR szDisplay[MAX_PATH];
  1084. BROWSEINFOA biA;
  1085. Assert(pbiW);
  1086. if((IsPlatformWinNT() == S_OK) && g_rOSVersionInfo.dwMajorVersion >= 5)
  1087. pidl = SHBrowseForFolderW(pbiW); // this is only for NT5
  1088. else
  1089. {
  1090. pszTitle = PszToANSI(CP_ACP, pbiW->lpszTitle);
  1091. if (!pszTitle)
  1092. goto exit;
  1093. biA = *((BROWSEINFOA*)pbiW);
  1094. biA.lpszTitle = pszTitle;
  1095. biA.pszDisplayName = szDisplay;
  1096. pidl = SHBrowseForFolderA(&biA);
  1097. if (pidl)
  1098. {
  1099. if (0 == MultiByteToWideChar(CP_ACP, 0, biA.pszDisplayName, -1, pbiW->pszDisplayName, MAX_PATH))
  1100. {
  1101. SHFree(pidl);
  1102. pidl = NULL;
  1103. }
  1104. }
  1105. }
  1106. exit:
  1107. MemFree(pszTitle);
  1108. return pidl;
  1109. }
  1110. BOOL BrowseForFolderW(HINSTANCE hInst, HWND hwnd, WCHAR *pwszDir, int cch, int idsText, BOOL fFileSysOnly)
  1111. {
  1112. LPITEMIDLIST plist;
  1113. BROWSEINFOW bi;
  1114. BROWSEFOLDERINFOW bfi;
  1115. BOOL fRet = FALSE;
  1116. WCHAR *pwsz = NULL,
  1117. wszTemp[MAX_PATH];
  1118. CHAR szRes[256];
  1119. Assert(pwszDir != NULL);
  1120. Assert(cch >= MAX_PATH);
  1121. // Don't have access to all wrappers in msoert so
  1122. // must do conversion ourselves for LoadStringW
  1123. LoadString(hInst, idsText, szRes, ARRAYSIZE(szRes));
  1124. pwsz = PszToUnicode(CP_ACP, szRes);
  1125. if (!pwsz)
  1126. goto exit;
  1127. bfi.pwsz = pwszDir;
  1128. bfi.fFileSysOnly = fFileSysOnly;
  1129. bi.hwndOwner = hwnd;
  1130. bi.pidlRoot = NULL;
  1131. bi.pszDisplayName = wszTemp;
  1132. bi.lpszTitle = pwsz;
  1133. bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
  1134. bi.lpfn = BrowseCallbackProcW;
  1135. bi.lParam = (LPARAM)&bfi;
  1136. plist = SHBrowseForFolderAthW(&bi);
  1137. if (plist != NULL)
  1138. {
  1139. fRet = SHGetPathFromIDListAthW(plist, pwszDir);
  1140. SHFree(plist);
  1141. }
  1142. exit:
  1143. MemFree(pwsz);
  1144. return(fRet);
  1145. }
  1146. int BrowseCallbackProcW(HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData)
  1147. {
  1148. BOOL fRet;
  1149. UINT type;
  1150. WCHAR wsz[MAX_PATH];
  1151. BROWSEFOLDERINFOW *pbfi;
  1152. switch (msg)
  1153. {
  1154. case BFFM_INITIALIZED:
  1155. pbfi = (BROWSEFOLDERINFOW *)lpData;
  1156. Assert(pbfi != NULL);
  1157. SendMessage(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM)pbfi->pwsz);
  1158. break;
  1159. case BFFM_SELCHANGED:
  1160. pbfi = (BROWSEFOLDERINFOW *)lpData;
  1161. Assert(pbfi != NULL);
  1162. fRet = SHGetPathFromIDListAthW((LPITEMIDLIST)lParam, wsz);
  1163. if (fRet)
  1164. {
  1165. if (L':' == wsz[1] && L'\\' == wsz[2])
  1166. {
  1167. wsz[3] = 0;
  1168. if (S_OK == IsPlatformWinNT())
  1169. type = GetDriveTypeW(wsz);
  1170. else
  1171. {
  1172. // Since we can't fail in this function, we need to do some kind
  1173. // of conversion that doesn't require memory allocations, etc.
  1174. // Since drives always must be ansi, can do the conversion in this
  1175. // really ugly way.
  1176. CHAR szDir[] = "a:\\";
  1177. AssertSz(0 == ((LPSTR)wsz)[1], "The char is not a unicode ANSI char");
  1178. *szDir = *((LPSTR)wsz);
  1179. type = GetDriveType(szDir);
  1180. }
  1181. if (pbfi->fFileSysOnly)
  1182. fRet = (type == DRIVE_FIXED);
  1183. else
  1184. fRet = (type == DRIVE_FIXED || type == DRIVE_REMOVABLE || type == DRIVE_REMOTE);
  1185. }
  1186. else
  1187. {
  1188. fRet = !pbfi->fFileSysOnly;
  1189. }
  1190. }
  1191. SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM)fRet);
  1192. break;
  1193. }
  1194. return(0);
  1195. }
  1196. int BrowseCallbackProcA(HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData)
  1197. {
  1198. BOOL fRet;
  1199. UINT type;
  1200. CHAR sz[MAX_PATH];
  1201. BROWSEFOLDERINFOA *pbfi;
  1202. switch (msg)
  1203. {
  1204. case BFFM_INITIALIZED:
  1205. pbfi = (BROWSEFOLDERINFOA *)lpData;
  1206. Assert(pbfi != NULL);
  1207. SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)pbfi->psz);
  1208. break;
  1209. case BFFM_SELCHANGED:
  1210. pbfi = (BROWSEFOLDERINFOA *)lpData;
  1211. Assert(pbfi != NULL);
  1212. fRet = SHGetPathFromIDList((LPITEMIDLIST)lParam, sz);
  1213. if (fRet)
  1214. {
  1215. // Only reason to do this check is to see if we have
  1216. // some funky chars in the filename. This will protect us
  1217. // from selecting files with non-ANSI chars in them.
  1218. if (PathFileExists(sz))
  1219. {
  1220. if (':' == sz[1] && '\\' == sz[2])
  1221. {
  1222. sz[3] = 0;
  1223. type = GetDriveType(sz);
  1224. if (pbfi->fFileSysOnly)
  1225. fRet = (type == DRIVE_FIXED);
  1226. else
  1227. fRet = (type == DRIVE_FIXED || type == DRIVE_REMOVABLE || type == DRIVE_REMOTE);
  1228. }
  1229. else
  1230. {
  1231. fRet = !pbfi->fFileSysOnly;
  1232. }
  1233. }
  1234. else
  1235. fRet = FALSE;
  1236. }
  1237. SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM)fRet);
  1238. break;
  1239. }
  1240. return(0);
  1241. }
  1242. HRESULT IsPlatformWinNT(void)
  1243. {
  1244. return (g_rOSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? S_OK : S_FALSE;
  1245. }
  1246. void UpdateRebarBandColors(HWND hwndRebar)
  1247. {
  1248. REBARBANDINFO rbbi;
  1249. UINT i;
  1250. UINT cBands;
  1251. // First find the band with the toolbar
  1252. cBands = (UINT) SendMessage(hwndRebar, RB_GETBANDCOUNT, 0, 0);
  1253. ZeroMemory(&rbbi, sizeof(rbbi));
  1254. rbbi.cbSize = sizeof(REBARBANDINFO);
  1255. rbbi.fMask = RBBIM_ID;
  1256. for (i = 0; i < cBands; i++)
  1257. {
  1258. SendMessage(hwndRebar, RB_GETBANDINFO, i, (LPARAM) &rbbi);
  1259. ZeroMemory(&rbbi, sizeof(rbbi));
  1260. rbbi.cbSize = sizeof(REBARBANDINFO);
  1261. rbbi.fMask = RBBIM_COLORS;
  1262. rbbi.clrFore = GetSysColor(COLOR_BTNTEXT);
  1263. rbbi.clrBack = GetSysColor(COLOR_BTNFACE);
  1264. SendMessage(hwndRebar, RB_SETBANDINFO, i, (LPARAM) (LPREBARBANDINFO) &rbbi);
  1265. }
  1266. }
  1267. #define RGB_BUTTONTEXT (RGB(000,000,000)) // black
  1268. #define RGB_BUTTONSHADOW (RGB(128,128,128)) // dark grey
  1269. #define RGB_BUTTONFACE (RGB(192,192,192)) // bright grey
  1270. #define RGB_BUTTONHILIGHT (RGB(255,255,255)) // white
  1271. #define RGB_TRANSPARENT (RGB(255,000,255)) // pink
  1272. inline BOOL fIsNT5() { return((g_rOSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (g_rOSVersionInfo.dwMajorVersion >= 5)); }
  1273. inline BOOL fIsWhistler() { return((fIsNT5() && g_rOSVersionInfo.dwMinorVersion >=1) ||
  1274. ((g_rOSVersionInfo.dwMajorVersion > 5) && (g_rOSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT))); }
  1275. /*
  1276. * This function loads an OE toolbar bitmap and maps 3D colors to the
  1277. * appropriate current scheme. We also map black and white so that we look
  1278. * good on high-contrast displays
  1279. */
  1280. HIMAGELIST LoadMappedToolbarBitmap(HINSTANCE hInst, int idBitmap, int cx)
  1281. {
  1282. static const COLORMAP SysColorMap[] = {
  1283. {RGB_BUTTONTEXT, COLOR_BTNTEXT}, // black
  1284. {RGB_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
  1285. {RGB_BUTTONFACE, COLOR_BTNFACE}, // bright grey
  1286. {RGB_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
  1287. };
  1288. #define NUM_DEFAULT_MAPS (sizeof(SysColorMap)/sizeof(COLORMAP))
  1289. COLORMAP DefaultColorMap[NUM_DEFAULT_MAPS];
  1290. HIMAGELIST himl;
  1291. HBITMAP hBmp;
  1292. BITMAP bm;
  1293. int cy=0;
  1294. /* Get system colors for the default color map */
  1295. for (int i=0; i < NUM_DEFAULT_MAPS; i++)
  1296. {
  1297. DefaultColorMap[i].from = SysColorMap[i].from;
  1298. DefaultColorMap[i].to = GetSysColor((int)SysColorMap[i].to);
  1299. }
  1300. if(!fIsWhistler())
  1301. hBmp = CreateMappedBitmap(hInst, idBitmap, 0, (COLORMAP *)&DefaultColorMap, NUM_DEFAULT_MAPS);
  1302. else
  1303. hBmp = CreateMappedBitmap(hInst, idBitmap, CMB_DIBSECTION, (COLORMAP *)&DefaultColorMap, NUM_DEFAULT_MAPS);
  1304. if (!hBmp)
  1305. return NULL;
  1306. if (GetObject(hBmp, sizeof(BITMAP), &bm))
  1307. cy = bm.bmHeight;
  1308. if(!fIsWhistler())
  1309. himl = ImageList_Create(cx, cy, ILC_COLORDDB|ILC_MASK, 4, 4);
  1310. else
  1311. himl = ImageList_Create(cx, cy, ILC_COLOR32|ILC_MASK, 4, 4);
  1312. if (!himl)
  1313. {
  1314. DeleteObject(hBmp);
  1315. return NULL;
  1316. }
  1317. // if(!fIsWhistler())
  1318. {
  1319. ImageList_AddMasked(himl, hBmp, RGB_TRANSPARENT);
  1320. ImageList_SetBkColor(himl, CLR_NONE);
  1321. }
  1322. DeleteObject(hBmp);
  1323. return himl;
  1324. }
  1325. HRESULT DoHotMailWizard(HWND hwndOwner, LPSTR pszUrl, LPSTR pszFriendly, RECT *prc, IUnknown *pUnkHost)
  1326. {
  1327. IHotWizard *pWiz=NULL;
  1328. HRESULT hr = S_OK;
  1329. LPWSTR pwszUrl = NULL,
  1330. pwszCaption = NULL;
  1331. IHotWizardHost *pHost = NULL;
  1332. if (pUnkHost)
  1333. IF_FAILEXIT(hr = pUnkHost->QueryInterface(IID_IHotWizardHost, (LPVOID *)&pHost));
  1334. // create and show the wizard
  1335. IF_FAILEXIT(hr = CoCreateInstance(CLSID_OEHotMailWizard, NULL, CLSCTX_INPROC_SERVER, IID_IHotWizard, (LPVOID*)&pWiz));
  1336. IF_NULLEXIT(pwszUrl = PszToUnicode(CP_ACP, pszUrl));
  1337. IF_NULLEXIT(pwszCaption = PszToUnicode(CP_ACP, pszFriendly));
  1338. IF_FAILEXIT(hr = pWiz->Show(hwndOwner, pwszUrl, pwszCaption, pHost, prc));
  1339. exit:
  1340. MemFree(pwszUrl);
  1341. MemFree(pwszCaption);
  1342. ReleaseObj(pWiz);
  1343. ReleaseObj(pHost);
  1344. return hr;
  1345. }
  1346. BOOL fGetBrowserUrlEncoding(LPDWORD pdwFlags)
  1347. {
  1348. DWORD dwUrlEncodingDisableUTF8;
  1349. DWORD dwSize = sizeof(dwUrlEncodingDisableUTF8);
  1350. BOOL fDefault = FALSE;
  1351. DWORD dwFlags = *pdwFlags;
  1352. BOOL fret = TRUE;
  1353. if (ERROR_SUCCESS == SHRegGetUSValue(c_szInternetSettingsPath, c_szUrlEncoding,
  1354. NULL, (LPBYTE) &dwUrlEncodingDisableUTF8, &dwSize,
  1355. FALSE, (LPVOID) &fDefault, sizeof(fDefault)))
  1356. {
  1357. if (!dwUrlEncodingDisableUTF8)
  1358. dwFlags |= DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8;
  1359. else
  1360. dwFlags |= DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8;
  1361. *pdwFlags = dwFlags;
  1362. }
  1363. else fret = FALSE;
  1364. return fret;
  1365. }