Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

467 lines
13 KiB

  1. #include "privcpp.h"
  2. #include "shlwapi.h"
  3. extern HINSTANCE g_hinst;
  4. //////////////////////////////////////////////////////////////////////
  5. //
  6. // Icon Helper Functions
  7. //
  8. //////////////////////////////////////////////////////////////////////
  9. void IconDraw(LPIC lpic, HDC hdc, LPRECT lprc)
  10. {
  11. //
  12. // draw's the icon and the text to the specfied DC in the given
  13. // bounding rect.
  14. //
  15. DebugMsg(DM_TRACE, "pack - IconDraw() called.");
  16. DebugMsg(DM_TRACE, " left==%d,top==%d,right==%d,bottom==%d",
  17. lprc->left,lprc->top,lprc->right,lprc->bottom);
  18. // make sure we'll fit in the given rect
  19. if (((lpic->rc.right-lpic->rc.left) > (lprc->right - lprc->left)) ||
  20. ((lpic->rc.bottom-lpic->rc.top) > (lprc->bottom - lprc->top)))
  21. return;
  22. // Draw the icon
  23. if (lpic->hDlgIcon)
  24. DrawIcon(hdc, (lprc->left + lprc->right - g_cxIcon) / 2,
  25. (lprc->top + lprc->bottom - lpic->rc.bottom) / 2, lpic->hDlgIcon);
  26. if ((lpic->szIconText) && *(lpic->szIconText))
  27. {
  28. HFONT hfont = SelectFont(hdc, g_hfontTitle);
  29. RECT rcText;
  30. rcText.left = lprc->left;
  31. rcText.right = lprc->right;
  32. rcText.top = (lprc->top + lprc->bottom - lpic->rc.bottom) / 2 + g_cyIcon + 1;
  33. rcText.bottom = lprc->bottom;
  34. DrawText(hdc, lpic->szIconText, -1, &rcText,
  35. DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | DT_SINGLELINE | DT_TOP);
  36. if (hfont)
  37. SelectObject(hdc, hfont);
  38. }
  39. }
  40. LPIC IconCreate(void)
  41. {
  42. //
  43. // allocates space for our icon structure which holds icon index,
  44. // the icon path, the handle to the icon, and the icon text
  45. // return: NULL on failure
  46. // a valid pointer on success
  47. //
  48. DebugMsg(DM_TRACE, "pack - IconCreate() called.");
  49. // Allocate memory for the IC structure
  50. return (LPIC)GlobalAlloc(GPTR, sizeof(IC));
  51. }
  52. LPIC IconCreateFromFile(LPCTSTR lpstrFile)
  53. {
  54. //
  55. // initializes an IC structure (defined in pack2.h) from a given
  56. // filename.
  57. // return: NULL on failure
  58. // a valid pointer on success
  59. //
  60. LPIC lpic;
  61. DebugMsg(DM_TRACE, "pack - IconCreateFromFile() called.");
  62. if (lpic = IconCreate())
  63. {
  64. // Get the icon
  65. lstrcpy(lpic->szIconPath, lpstrFile);
  66. lpic->iDlgIcon = 0;
  67. if (*(lpic->szIconPath))
  68. GetCurrentIcon(lpic);
  69. // Get the icon text -- calls ILGetDisplayName
  70. //
  71. GetDisplayName(lpic->szIconText, lpstrFile);
  72. if (!IconCalcSize(lpic)) {
  73. if (lpic->hDlgIcon)
  74. DestroyIcon(lpic->hDlgIcon);
  75. GlobalFree(lpic);
  76. lpic = NULL;
  77. }
  78. }
  79. return lpic;
  80. }
  81. BOOL IconCalcSize(LPIC lpic)
  82. {
  83. HDC hdcWnd;
  84. RECT rcText = { 0 };
  85. SIZE Image;
  86. HFONT hfont;
  87. DebugMsg(DM_TRACE, "pack - IconCalcSize called.");
  88. // get the window DC, and make a DC compatible to it
  89. if (!(hdcWnd = GetDC(NULL))) {
  90. DebugMsg(DM_TRACE, " couldn't get DC!!");
  91. return FALSE;
  92. }
  93. ASSERT(lpic);
  94. if (lpic->szIconText && *(lpic->szIconText))
  95. {
  96. SetRect(&rcText, 0, 0, g_cxArrange, g_cyArrange);
  97. // Set the icon text rectangle, and the icon font
  98. hfont = SelectFont(hdcWnd, g_hfontTitle);
  99. // Figure out how large the text region will be
  100. rcText.bottom = DrawText(hdcWnd, lpic->szIconText, -1, &rcText,
  101. DT_CALCRECT | DT_WORDBREAK | DT_NOPREFIX | DT_SINGLELINE);
  102. if (hfont)
  103. SelectObject(hdcWnd, hfont);
  104. }
  105. // Compute the image size
  106. rcText.right++;
  107. Image.cx = (rcText.right > g_cxIcon) ? rcText.right : g_cxIcon;
  108. Image.cy = g_cyIcon + rcText.bottom + 1;
  109. // grow the image a bit
  110. Image.cx += Image.cx / 4;
  111. Image.cy += Image.cy / 8;
  112. lpic->rc.right = Image.cx;
  113. lpic->rc.bottom = Image.cy;
  114. DebugMsg(DM_TRACE," lpic->rc.right==%d,lpic->rc.bottom==%d",
  115. lpic->rc.right,lpic->rc.bottom);
  116. return TRUE;
  117. }
  118. void GetCurrentIcon(LPIC lpic)
  119. {
  120. //
  121. // gets the current icon associated with the path stored in lpic->szIconPath
  122. // if it can't extract the icon associated with the file, it just gets
  123. // the standard application icon
  124. //
  125. WORD wIcon = (WORD)lpic->iDlgIcon;
  126. DebugMsg(DM_TRACE, "pack - GetCurrentIcon() called.");
  127. if (lpic->hDlgIcon)
  128. DestroyIcon(lpic->hDlgIcon);
  129. if (!lpic->szIconPath || *lpic->szIconPath == TEXT('\0'))
  130. lpic->hDlgIcon = (HICON)LoadImage(g_hinst, MAKEINTRESOURCE(IDI_PACKAGER),
  131. IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
  132. else if (!(lpic->hDlgIcon = ExtractAssociatedIcon(g_hinst, lpic->szIconPath, &wIcon)))
  133. lpic->hDlgIcon = (HICON)LoadImage(g_hinst, MAKEINTRESOURCE(IDI_PACKAGER),
  134. IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
  135. }
  136. void GetDisplayName(LPTSTR szName, LPCTSTR szPath)
  137. {
  138. LPTSTR pszTemp = PathFindFileName(szPath);
  139. lstrcpy(szName, pszTemp);
  140. }
  141. /* ReplaceExtension() - Replaces the extension of the temp file.
  142. *
  143. * This routine ensures that the temp file has the same extension as the
  144. * original file, so that the ShellExecute() will load the same server..
  145. */
  146. VOID ReplaceExtension(LPTSTR lpstrTempFile,LPTSTR lpstrOrigFile)
  147. {
  148. LPTSTR lpstrBack = NULL;
  149. DebugMsg(DM_TRACE, " ReplaceExtension() called.");
  150. // Get temp file extension
  151. while (*lpstrTempFile)
  152. {
  153. if (*lpstrTempFile == '\\')
  154. lpstrBack = lpstrTempFile;
  155. lpstrTempFile++;
  156. }
  157. while (lpstrBack && *lpstrBack && *lpstrBack != '.')
  158. lpstrBack++;
  159. if (lpstrBack && *lpstrBack)
  160. lpstrTempFile = lpstrBack + 1;
  161. // Get original file extension
  162. while (*lpstrOrigFile)
  163. {
  164. if (*lpstrOrigFile == '\\')
  165. lpstrBack = lpstrOrigFile;
  166. lpstrOrigFile++;
  167. }
  168. while (lpstrBack && *lpstrBack && *lpstrBack != '.')
  169. lpstrBack++;
  170. if (lpstrBack && *lpstrBack)
  171. {
  172. lpstrOrigFile = lpstrBack + 1;
  173. // Move the extension on over
  174. lstrcpy(lpstrTempFile, lpstrOrigFile);
  175. }
  176. else
  177. {
  178. /* Wipe out the extension altogether */
  179. *lpstrTempFile = 0;
  180. }
  181. }
  182. /////////////////////////////////////////////////////////////////////////
  183. //
  184. // Stream Helper Functions
  185. //
  186. /////////////////////////////////////////////////////////////////////////
  187. HRESULT CopyFileToStream(LPTSTR lpFileName, IStream* pstm)
  188. {
  189. //
  190. // copies the given file to the current seek pointer in the given stream
  191. // return: S_OK -- successfully copied
  192. // E_POINTER -- one of the pointers was NULL
  193. // E_OUTOFMEMORY -- out of memory
  194. // E_FAIL -- other error
  195. //
  196. LPVOID lpMem;
  197. HANDLE hFile = INVALID_HANDLE_VALUE;
  198. HRESULT hr;
  199. DWORD dwSizeLow;
  200. DWORD dwSizeHigh;
  201. DWORD dwPosLow = 0L;
  202. LONG lPosHigh = 0L;
  203. DWORD cbRead = BUFFERSIZE;
  204. DWORD cbWritten = BUFFERSIZE;
  205. DebugMsg(DM_TRACE,"pack - CopyFileToStream called.");
  206. if (!pstm || !lpFileName) {
  207. DebugMsg(DM_TRACE," bad pointer!!");
  208. return E_POINTER;
  209. }
  210. // Allocate memory buffer for tranfer operation...
  211. if (!(lpMem = (LPVOID)GlobalAlloc(GPTR, BUFFERSIZE))) {
  212. DebugMsg(DM_TRACE, " couldn't alloc memory buffer!!");
  213. hr = E_OUTOFMEMORY;
  214. goto ErrRet;
  215. }
  216. // open file to copy to stream
  217. hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READWRITE, NULL,
  218. OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  219. if (hFile == INVALID_HANDLE_VALUE) {
  220. DebugMsg(DM_TRACE, " couldn't open file!!");
  221. goto ErrRet;
  222. }
  223. // Figure out how much to copy...
  224. dwSizeLow = GetFileSize(hFile, &dwSizeHigh);
  225. ASSERT(dwSizeHigh == 0);
  226. SetFilePointer(hFile, 0L, NULL, FILE_BEGIN);
  227. // read in the file, and write to stream
  228. while (cbRead == BUFFERSIZE && cbWritten == BUFFERSIZE)
  229. {
  230. ReadFile(hFile, lpMem, BUFFERSIZE, &cbRead, NULL);
  231. pstm->Write(lpMem, cbRead, &cbWritten);
  232. }
  233. // verify that we are now at end of block to copy
  234. dwPosLow = SetFilePointer(hFile, 0L, &lPosHigh, FILE_CURRENT);
  235. ASSERT(lPosHigh == 0);
  236. if (dwPosLow != dwSizeLow) {
  237. DebugMsg(DM_TRACE, " error copying file!!");
  238. hr = E_FAIL;
  239. goto ErrRet;
  240. }
  241. hr = S_OK;
  242. ErrRet:
  243. if (hFile != INVALID_HANDLE_VALUE)
  244. CloseHandle(hFile);
  245. if (lpMem)
  246. GlobalFree((HANDLE)lpMem);
  247. return hr;
  248. }
  249. HRESULT CopyStreamToFile(IStream* pstm, LPTSTR lpFileName)
  250. {
  251. //
  252. // copies the contents of the given stream from the current seek pointer
  253. // to the end of the stream into the given file.
  254. //
  255. // NOTE: the given filename must not exist, if it does, the function fails
  256. // with E_FAIL
  257. //
  258. // return: S_OK -- successfully copied
  259. // E_POINTER -- one of the pointers was NULL
  260. // E_OUTOFMEMORY -- out of memory
  261. // E_FAIL -- other error
  262. //
  263. LPVOID lpMem;
  264. HANDLE hFile = INVALID_HANDLE_VALUE;
  265. HRESULT hr = S_OK;
  266. DWORD cbRead = BUFFERSIZE;
  267. DWORD cbWritten = BUFFERSIZE;
  268. ULARGE_INTEGER uli;
  269. LARGE_INTEGER li = { 0L, 0L};
  270. ULARGE_INTEGER uliPos;
  271. DebugMsg(DM_TRACE,"pack - CopyStreamToFile called.");
  272. // pstm must be a valid stream that is open for reading
  273. // lpFileName must be a valid filename to be written
  274. //
  275. if (!pstm || !lpFileName)
  276. return E_POINTER;
  277. // Allocate memory buffer...
  278. if (!(lpMem = (LPVOID)GlobalAlloc(GPTR, BUFFERSIZE))) {
  279. DebugMsg(DM_TRACE, " couldn't alloc memory buffer!!");
  280. hr = E_OUTOFMEMORY;
  281. goto ErrRet;
  282. }
  283. // open file to receive stream data
  284. hFile = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL,
  285. CREATE_NEW, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  286. if (hFile == INVALID_HANDLE_VALUE) {
  287. DebugMsg(DM_TRACE, " couldn't open file!!");
  288. hr = E_FAIL;
  289. goto ErrRet;
  290. }
  291. // get the number of bytes to copy
  292. pstm->Seek(li, STREAM_SEEK_CUR, &uliPos);
  293. pstm->Seek(li, STREAM_SEEK_END, &uli);
  294. ASSERT(uliPos.HighPart == uli.HighPart); // can't copy more than a DWORD
  295. li.HighPart = uliPos.HighPart;
  296. li.LowPart = uliPos.LowPart;
  297. pstm->Seek(li, STREAM_SEEK_SET, NULL);
  298. // read in the stream, and write to the file
  299. while (cbRead == BUFFERSIZE && cbWritten == BUFFERSIZE)
  300. {
  301. hr = pstm->Read(lpMem, BUFFERSIZE, &cbRead);
  302. WriteFile(hFile, lpMem, cbRead, &cbWritten, NULL);
  303. }
  304. // li.HighPart = 0L;
  305. // li.LowPart = 0L;
  306. // verify that we are now at end of stream
  307. // pstm->Seek(li, STREAM_SEEK_CUR, &uliPos);
  308. // if (uliPos.LowPart != uli.LowPart || uliPos.HighPart != uli.HighPart) {
  309. if (hr != S_OK)
  310. {
  311. DebugMsg(DM_TRACE, " error copying file!!");
  312. hr = E_FAIL;
  313. goto ErrRet;
  314. }
  315. ErrRet:
  316. if (hFile != INVALID_HANDLE_VALUE)
  317. CloseHandle(hFile);
  318. if (lpMem)
  319. GlobalFree((HANDLE)lpMem);
  320. return hr;
  321. }
  322. // FEATURE: write persistence formats in UNICODE!
  323. HRESULT StringReadFromStream(IStream* pstm, LPSTR pszBuf, UINT cchBuf)
  324. {
  325. //
  326. // read byte by byte until we hit the null terminating char
  327. // return: the number of bytes read
  328. //
  329. UINT cch = 0;
  330. do {
  331. pstm->Read(pszBuf, sizeof(CHAR), NULL);
  332. cch++;
  333. } while (*pszBuf++ && cch <= cchBuf);
  334. return cch;
  335. }
  336. DWORD _CBString(LPCSTR psz)
  337. {
  338. return sizeof(psz[0]) * (lstrlenA(psz) + 1);
  339. }
  340. HRESULT StringWriteToStream(IStream* pstm, LPCSTR psz, DWORD *pdwWrite)
  341. {
  342. DWORD dwWrite;
  343. DWORD dwSize = _CBString(psz);
  344. HRESULT hr = pstm->Write(psz, dwSize, &dwWrite);
  345. if (SUCCEEDED(hr))
  346. *pdwWrite += dwWrite;
  347. return hr;
  348. }
  349. // parse pszPath into a unquoted path string and put the args in pszArgs
  350. //
  351. // returns:
  352. // TRUE we verified the thing exists
  353. // FALSE it may not exist
  354. //
  355. // taken from \ccshell\shell32\link.c
  356. //
  357. BOOL PathSeparateArgs(LPTSTR pszPath, LPTSTR pszArgs)
  358. {
  359. LPTSTR pszT;
  360. PathRemoveBlanks(pszPath);
  361. // if the unquoted sting exists as a file just use it
  362. if (PathFileExists(pszPath))
  363. {
  364. *pszArgs = 0;
  365. return TRUE;
  366. }
  367. pszT = PathGetArgs(pszPath);
  368. if (*pszT)
  369. *(pszT - 1) = TEXT('\0');
  370. lstrcpy(pszArgs, pszT);
  371. PathUnquoteSpaces(pszPath);
  372. return FALSE;
  373. }