#include "privcpp.h" #include "shlwapi.h" extern HINSTANCE g_hinst; ////////////////////////////////////////////////////////////////////// // // Icon Helper Functions // ////////////////////////////////////////////////////////////////////// void IconDraw(LPIC lpic, HDC hdc, LPRECT lprc) { // // draw's the icon and the text to the specfied DC in the given // bounding rect. // DebugMsg(DM_TRACE, "pack - IconDraw() called."); DebugMsg(DM_TRACE, " left==%d,top==%d,right==%d,bottom==%d", lprc->left,lprc->top,lprc->right,lprc->bottom); // make sure we'll fit in the given rect if (((lpic->rc.right-lpic->rc.left) > (lprc->right - lprc->left)) || ((lpic->rc.bottom-lpic->rc.top) > (lprc->bottom - lprc->top))) return; // Draw the icon if (lpic->hDlgIcon) DrawIcon(hdc, (lprc->left + lprc->right - g_cxIcon) / 2, (lprc->top + lprc->bottom - lpic->rc.bottom) / 2, lpic->hDlgIcon); if ((lpic->szIconText) && *(lpic->szIconText)) { HFONT hfont = SelectFont(hdc, g_hfontTitle); RECT rcText; rcText.left = lprc->left; rcText.right = lprc->right; rcText.top = (lprc->top + lprc->bottom - lpic->rc.bottom) / 2 + g_cyIcon + 1; rcText.bottom = lprc->bottom; DrawText(hdc, lpic->szIconText, -1, &rcText, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | DT_SINGLELINE | DT_TOP); if (hfont) SelectObject(hdc, hfont); } } LPIC IconCreate(void) { // // allocates space for our icon structure which holds icon index, // the icon path, the handle to the icon, and the icon text // return: NULL on failure // a valid pointer on success // DebugMsg(DM_TRACE, "pack - IconCreate() called."); // Allocate memory for the IC structure return (LPIC)GlobalAlloc(GPTR, sizeof(IC)); } LPIC IconCreateFromFile(LPCTSTR lpstrFile) { // // initializes an IC structure (defined in pack2.h) from a given // filename. // return: NULL on failure // a valid pointer on success // LPIC lpic; DebugMsg(DM_TRACE, "pack - IconCreateFromFile() called."); if (lpic = IconCreate()) { // Get the icon lstrcpy(lpic->szIconPath, lpstrFile); lpic->iDlgIcon = 0; if (*(lpic->szIconPath)) GetCurrentIcon(lpic); // Get the icon text -- calls ILGetDisplayName // GetDisplayName(lpic->szIconText, lpstrFile); if (!IconCalcSize(lpic)) { if (lpic->hDlgIcon) DestroyIcon(lpic->hDlgIcon); GlobalFree(lpic); lpic = NULL; } } return lpic; } BOOL IconCalcSize(LPIC lpic) { HDC hdcWnd; RECT rcText = { 0 }; SIZE Image; HFONT hfont; DebugMsg(DM_TRACE, "pack - IconCalcSize called."); // get the window DC, and make a DC compatible to it if (!(hdcWnd = GetDC(NULL))) { DebugMsg(DM_TRACE, " couldn't get DC!!"); return FALSE; } ASSERT(lpic); if (lpic->szIconText && *(lpic->szIconText)) { SetRect(&rcText, 0, 0, g_cxArrange, g_cyArrange); // Set the icon text rectangle, and the icon font hfont = SelectFont(hdcWnd, g_hfontTitle); // Figure out how large the text region will be rcText.bottom = DrawText(hdcWnd, lpic->szIconText, -1, &rcText, DT_CALCRECT | DT_WORDBREAK | DT_NOPREFIX | DT_SINGLELINE); if (hfont) SelectObject(hdcWnd, hfont); } // Compute the image size rcText.right++; Image.cx = (rcText.right > g_cxIcon) ? rcText.right : g_cxIcon; Image.cy = g_cyIcon + rcText.bottom + 1; // grow the image a bit Image.cx += Image.cx / 4; Image.cy += Image.cy / 8; lpic->rc.right = Image.cx; lpic->rc.bottom = Image.cy; DebugMsg(DM_TRACE," lpic->rc.right==%d,lpic->rc.bottom==%d", lpic->rc.right,lpic->rc.bottom); return TRUE; } void GetCurrentIcon(LPIC lpic) { // // gets the current icon associated with the path stored in lpic->szIconPath // if it can't extract the icon associated with the file, it just gets // the standard application icon // WORD wIcon = (WORD)lpic->iDlgIcon; DebugMsg(DM_TRACE, "pack - GetCurrentIcon() called."); if (lpic->hDlgIcon) DestroyIcon(lpic->hDlgIcon); if (!lpic->szIconPath || *lpic->szIconPath == TEXT('\0')) lpic->hDlgIcon = (HICON)LoadImage(g_hinst, MAKEINTRESOURCE(IDI_PACKAGER), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); else if (!(lpic->hDlgIcon = ExtractAssociatedIcon(g_hinst, lpic->szIconPath, &wIcon))) lpic->hDlgIcon = (HICON)LoadImage(g_hinst, MAKEINTRESOURCE(IDI_PACKAGER), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); } void GetDisplayName(LPTSTR szName, LPCTSTR szPath) { LPTSTR pszTemp = PathFindFileName(szPath); lstrcpy(szName, pszTemp); } /* ReplaceExtension() - Replaces the extension of the temp file. * * This routine ensures that the temp file has the same extension as the * original file, so that the ShellExecute() will load the same server.. */ VOID ReplaceExtension(LPTSTR lpstrTempFile,LPTSTR lpstrOrigFile) { LPTSTR lpstrBack = NULL; DebugMsg(DM_TRACE, " ReplaceExtension() called."); // Get temp file extension while (*lpstrTempFile) { if (*lpstrTempFile == '\\') lpstrBack = lpstrTempFile; lpstrTempFile++; } while (lpstrBack && *lpstrBack && *lpstrBack != '.') lpstrBack++; if (lpstrBack && *lpstrBack) lpstrTempFile = lpstrBack + 1; // Get original file extension while (*lpstrOrigFile) { if (*lpstrOrigFile == '\\') lpstrBack = lpstrOrigFile; lpstrOrigFile++; } while (lpstrBack && *lpstrBack && *lpstrBack != '.') lpstrBack++; if (lpstrBack && *lpstrBack) { lpstrOrigFile = lpstrBack + 1; // Move the extension on over lstrcpy(lpstrTempFile, lpstrOrigFile); } else { /* Wipe out the extension altogether */ *lpstrTempFile = 0; } } ///////////////////////////////////////////////////////////////////////// // // Stream Helper Functions // ///////////////////////////////////////////////////////////////////////// HRESULT CopyFileToStream(LPTSTR lpFileName, IStream* pstm) { // // copies the given file to the current seek pointer in the given stream // return: S_OK -- successfully copied // E_POINTER -- one of the pointers was NULL // E_OUTOFMEMORY -- out of memory // E_FAIL -- other error // LPVOID lpMem; HANDLE hFile = INVALID_HANDLE_VALUE; HRESULT hr; DWORD dwSizeLow; DWORD dwSizeHigh; DWORD dwPosLow = 0L; LONG lPosHigh = 0L; DWORD cbRead = BUFFERSIZE; DWORD cbWritten = BUFFERSIZE; DebugMsg(DM_TRACE,"pack - CopyFileToStream called."); if (!pstm || !lpFileName) { DebugMsg(DM_TRACE," bad pointer!!"); return E_POINTER; } // Allocate memory buffer for tranfer operation... if (!(lpMem = (LPVOID)GlobalAlloc(GPTR, BUFFERSIZE))) { DebugMsg(DM_TRACE, " couldn't alloc memory buffer!!"); hr = E_OUTOFMEMORY; goto ErrRet; } // open file to copy to stream hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READWRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) { DebugMsg(DM_TRACE, " couldn't open file!!"); goto ErrRet; } // Figure out how much to copy... dwSizeLow = GetFileSize(hFile, &dwSizeHigh); ASSERT(dwSizeHigh == 0); SetFilePointer(hFile, 0L, NULL, FILE_BEGIN); // read in the file, and write to stream while (cbRead == BUFFERSIZE && cbWritten == BUFFERSIZE) { ReadFile(hFile, lpMem, BUFFERSIZE, &cbRead, NULL); pstm->Write(lpMem, cbRead, &cbWritten); } // verify that we are now at end of block to copy dwPosLow = SetFilePointer(hFile, 0L, &lPosHigh, FILE_CURRENT); ASSERT(lPosHigh == 0); if (dwPosLow != dwSizeLow) { DebugMsg(DM_TRACE, " error copying file!!"); hr = E_FAIL; goto ErrRet; } hr = S_OK; ErrRet: if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); if (lpMem) GlobalFree((HANDLE)lpMem); return hr; } HRESULT CopyStreamToFile(IStream* pstm, LPTSTR lpFileName) { // // copies the contents of the given stream from the current seek pointer // to the end of the stream into the given file. // // NOTE: the given filename must not exist, if it does, the function fails // with E_FAIL // // return: S_OK -- successfully copied // E_POINTER -- one of the pointers was NULL // E_OUTOFMEMORY -- out of memory // E_FAIL -- other error // LPVOID lpMem; HANDLE hFile = INVALID_HANDLE_VALUE; HRESULT hr = S_OK; DWORD cbRead = BUFFERSIZE; DWORD cbWritten = BUFFERSIZE; ULARGE_INTEGER uli; LARGE_INTEGER li = { 0L, 0L}; ULARGE_INTEGER uliPos; DebugMsg(DM_TRACE,"pack - CopyStreamToFile called."); // pstm must be a valid stream that is open for reading // lpFileName must be a valid filename to be written // if (!pstm || !lpFileName) return E_POINTER; // Allocate memory buffer... if (!(lpMem = (LPVOID)GlobalAlloc(GPTR, BUFFERSIZE))) { DebugMsg(DM_TRACE, " couldn't alloc memory buffer!!"); hr = E_OUTOFMEMORY; goto ErrRet; } // open file to receive stream data hFile = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) { DebugMsg(DM_TRACE, " couldn't open file!!"); hr = E_FAIL; goto ErrRet; } // get the number of bytes to copy pstm->Seek(li, STREAM_SEEK_CUR, &uliPos); pstm->Seek(li, STREAM_SEEK_END, &uli); ASSERT(uliPos.HighPart == uli.HighPart); // can't copy more than a DWORD li.HighPart = uliPos.HighPart; li.LowPart = uliPos.LowPart; pstm->Seek(li, STREAM_SEEK_SET, NULL); // read in the stream, and write to the file while (cbRead == BUFFERSIZE && cbWritten == BUFFERSIZE) { hr = pstm->Read(lpMem, BUFFERSIZE, &cbRead); WriteFile(hFile, lpMem, cbRead, &cbWritten, NULL); } // li.HighPart = 0L; // li.LowPart = 0L; // verify that we are now at end of stream // pstm->Seek(li, STREAM_SEEK_CUR, &uliPos); // if (uliPos.LowPart != uli.LowPart || uliPos.HighPart != uli.HighPart) { if (hr != S_OK) { DebugMsg(DM_TRACE, " error copying file!!"); hr = E_FAIL; goto ErrRet; } ErrRet: if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); if (lpMem) GlobalFree((HANDLE)lpMem); return hr; } // FEATURE: write persistence formats in UNICODE! HRESULT StringReadFromStream(IStream* pstm, LPSTR pszBuf, UINT cchBuf) { // // read byte by byte until we hit the null terminating char // return: the number of bytes read // UINT cch = 0; do { pstm->Read(pszBuf, sizeof(CHAR), NULL); cch++; } while (*pszBuf++ && cch <= cchBuf); return cch; } DWORD _CBString(LPCSTR psz) { return sizeof(psz[0]) * (lstrlenA(psz) + 1); } HRESULT StringWriteToStream(IStream* pstm, LPCSTR psz, DWORD *pdwWrite) { DWORD dwWrite; DWORD dwSize = _CBString(psz); HRESULT hr = pstm->Write(psz, dwSize, &dwWrite); if (SUCCEEDED(hr)) *pdwWrite += dwWrite; return hr; } // parse pszPath into a unquoted path string and put the args in pszArgs // // returns: // TRUE we verified the thing exists // FALSE it may not exist // // taken from \ccshell\shell32\link.c // BOOL PathSeparateArgs(LPTSTR pszPath, LPTSTR pszArgs) { LPTSTR pszT; PathRemoveBlanks(pszPath); // if the unquoted sting exists as a file just use it if (PathFileExists(pszPath)) { *pszArgs = 0; return TRUE; } pszT = PathGetArgs(pszPath); if (*pszT) *(pszT - 1) = TEXT('\0'); lstrcpy(pszArgs, pszT); PathUnquoteSpaces(pszPath); return FALSE; }