#include "item.h" #include "parseinf.h" #include #include #include "parseinf.h" #include #ifdef AUTO_UPDATE #define NUM_PAGES 4 #else #define NUM_PAGES 3 #endif #define DEFAULT_LANG_CODEPAGE_PAIR 0x040904B0 #define MAX_QUERYPREFIX_LEN 512 #define MAX_QUERYSTRING_LEN 1024 // defined in utils.cpp extern LPCTSTR g_lpszUpdateInfo; extern LPCTSTR g_lpszCookieValue; extern LPCTSTR g_lpszSavedValue; /////////////////////////////////////////////////////////////////////////////// // functions that deal with web check // define a macro to make life easier #define QUIT_IF_FAIL if (FAILED(hr)) goto Exit void DestroyDialogIcon(HWND hDlg) { HICON hIcon = (HICON)SendDlgItemMessage( hDlg, IDC_STATIC_ICON, STM_GETICON, 0, 0); if (hIcon != NULL) DestroyIcon(hIcon); } /////////////////////////////////////////////////////////////////////////////// // functions that deal with property page 1 void InitPropPage1(HWND hDlg, LPARAM lParam) { BOOL bHasActiveX; BOOL bHasJava; SetWindowLongPtr(hDlg, DWLP_USER, lParam); LPCONTROLPIDL pcpidl = (LPCONTROLPIDL)((LPPROPSHEETPAGE)lParam)->lParam; if (pcpidl) { // draw control icon { HICON hIcon = ExtractIcon(g_hInst, GetStringInfo(pcpidl, SI_LOCATION), 0); if (hIcon == NULL) hIcon = GetDefaultOCIcon( pcpidl ); Assert(hIcon != NULL); SendDlgItemMessage(hDlg, IDC_STATIC_ICON, STM_SETICON, (WPARAM)hIcon, 0); } SetDlgItemText(hDlg, IDC_STATIC_CONTROL, GetStringInfo(pcpidl, SI_CONTROL)); SetDlgItemText(hDlg, IDC_STATIC_CREATION, GetStringInfo(pcpidl, SI_CREATION)); SetDlgItemText(hDlg, IDC_STATIC_LASTACCESS, GetStringInfo(pcpidl, SI_LASTACCESS)); SetDlgItemText(hDlg, IDC_STATIC_CLSID, GetStringInfo(pcpidl, SI_CLSID)); SetDlgItemText(hDlg, IDC_STATIC_CODEBASE, GetStringInfo(pcpidl, SI_CODEBASE)); TCHAR szBuf[MESSAGE_MAXSIZE]; GetContentBools( pcpidl, &bHasActiveX, &bHasJava ); if ( bHasJava ) { if ( bHasActiveX ) MLLoadString(IDS_PROPERTY_TYPE_MIXED, szBuf, MESSAGE_MAXSIZE); else MLLoadString(IDS_PROPERTY_TYPE_JAVA, szBuf, MESSAGE_MAXSIZE); } else MLLoadString(IDS_PROPERTY_TYPE_ACTX, szBuf, MESSAGE_MAXSIZE); SetDlgItemText(hDlg, IDC_STATIC_TYPE, szBuf); GetStatus(pcpidl, szBuf, MESSAGE_MAXSIZE); SetDlgItemText(hDlg, IDC_STATIC_STATUS, szBuf); DWORD dwSizeSaved = GetSizeSaved(pcpidl); TCHAR szSize[20]; wsprintf(szSize, "%u", dwSizeSaved); // insert commas to separate groups of digits int nLen = lstrlen(szSize); int i = 0, j = (nLen <= 3 ? nLen : (nLen % 3)); TCHAR *pCh = szSize + j; for (; i < j; i++) szBuf[i] = szSize[i]; for (; *pCh != '\0'; i++, pCh++) { if (((pCh - szSize) % 3 == j) && (i > 0)) szBuf[i++] = ','; szBuf[i] = *pCh; } szBuf[i] = '\0'; TCHAR szBytes[BYTES_MAXSIZE]; MLLoadString(IDS_PROPERTY_BYTES, szBytes, BYTES_MAXSIZE); lstrcat(szBuf, TEXT(" ")); lstrcat(szBuf, szBytes); lstrcat(szBuf, TEXT(" (")); GetSizeSaved(pcpidl, szBuf + lstrlen(szBuf)); lstrcat(szBuf, TEXT(")")); SetDlgItemText(hDlg, IDC_STATIC_TOTALSIZE, szBuf); } } // Dialog proc for page 1 INT_PTR CALLBACK ControlItem_PropPage1Proc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE) GetWindowLongPtr(hDlg, DWLP_USER); LPCONTROLPIDL pcpidl = lpPropSheet ? (LPCONTROLPIDL)lpPropSheet->lParam : NULL; const static DWORD aIds[] = { IDC_STATIC_LABEL_TYPE, IDH_DLOAD_TYPE, IDC_STATIC_LABEL_CREATION, IDH_DLOAD_CREATED, IDC_STATIC_LABEL_LASTACCESS, IDH_DLOAD_LASTACC, IDC_STATIC_LABEL_TOTALSIZE, IDH_DLOAD_TOTALSIZE, IDC_STATIC_LABEL_CLSID, IDH_DLOAD_ID, IDC_STATIC_LABEL_STATUS, IDH_DLOAD_STATUS, IDC_STATIC_LABEL_CODEBASE, IDH_DLOAD_CODEBASE, IDC_STATIC_TYPE, IDH_DLOAD_TYPE, IDC_STATIC_CREATION, IDH_DLOAD_CREATED, IDC_STATIC_LASTACCESS, IDH_DLOAD_LASTACC, IDC_STATIC_TOTALSIZE, IDH_DLOAD_TOTALSIZE, IDC_STATIC_CLSID, IDH_DLOAD_ID, IDC_STATIC_STATUS, IDH_DLOAD_STATUS, IDC_STATIC_CODEBASE, IDH_DLOAD_CODEBASE, IDC_STATIC_CONTROL, IDH_DLOAD_OBJNAME, 0, 0 }; switch(message) { case WM_HELP: SHWinHelpOnDemandWrap((HWND)(((LPHELPINFO)lParam)->hItemHandle), "iexplore.hlp", HELP_WM_HELP, (DWORD_PTR)(LPSTR)aIds); break; case WM_CONTEXTMENU: SHWinHelpOnDemandWrap((HWND)wParam, "iexplore.hlp", HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID)aIds); break; case WM_INITDIALOG: InitPropPage1(hDlg, lParam); break; case WM_DESTROY: DestroyDialogIcon(hDlg); break; case WM_COMMAND: // user can't change anything, so we don't care about any messages break; default: return FALSE; } // end of switch return TRUE; } /////////////////////////////////////////////////////////////////////////////// // functions that deal with property page 2 int ListCtrl_InsertColumn( HWND hwnd, int nCol, LPCTSTR lpszColumnHeading, int nFormat, int nWidth, int nSubItem) { LV_COLUMN column; column.mask = LVCF_TEXT|LVCF_FMT; column.pszText = (LPTSTR)lpszColumnHeading; column.fmt = nFormat; if (nWidth != -1) { column.mask |= LVCF_WIDTH; column.cx = nWidth; } if (nSubItem != -1) { column.mask |= LVCF_SUBITEM; column.iSubItem = nSubItem; } return (int)::SendMessage(hwnd, LVM_INSERTCOLUMN, nCol, (LPARAM)&column); } BOOL ListCtrl_SetItemText( HWND hwnd, int nItem, int nSubItem, LPCTSTR lpszItem) { LV_ITEM lvi; lvi.mask = LVIF_TEXT; lvi.iItem = nItem; lvi.iSubItem = nSubItem; lvi.stateMask = 0; lvi.state = 0; lvi.pszText = (LPTSTR) lpszItem; lvi.iImage = 0; lvi.lParam = 0; return (BOOL)::SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&lvi); } int ListCtrl_InsertItem( HWND hwnd, UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam) { LV_ITEM item; item.mask = nMask; item.iItem = nItem; item.iSubItem = 0; item.pszText = (LPTSTR)lpszItem; item.state = nState; item.stateMask = nStateMask; item.iImage = nImage; item.lParam = lParam; return (int)::SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item); } void InitPropPage2(HWND hDlg, LPARAM lParam) { int iFileNameWidth = 0; SetWindowLongPtr(hDlg, DWLP_USER, lParam); LPCONTROLPIDL pcpidl = (LPCONTROLPIDL)((LPPROPSHEETPAGE)lParam)->lParam; UINT cTotalFiles = GetTotalNumOfFiles(pcpidl); { HICON hIcon = ExtractIcon(g_hInst, GetStringInfo(pcpidl, SI_LOCATION), 0); if (hIcon == NULL) hIcon = GetDefaultOCIcon( pcpidl ); Assert(hIcon != NULL); SendDlgItemMessage(hDlg, IDC_STATIC_ICON, STM_SETICON, (WPARAM)hIcon, 0); } // insert columns into file list box RECT rect; int nWidth; TCHAR szBuf[MAX_PATH]; HWND hwndCtrl = GetDlgItem(hDlg, IDC_DEPENDENCYLIST); Assert(::IsWindow(hwndCtrl)); GetClientRect(hwndCtrl, &rect); nWidth = rect.right - rect.left; MLLoadString(IDS_LISTTITLE_FILENAME, szBuf, MAX_PATH); iFileNameWidth = nWidth * 7 / 10; ListCtrl_InsertColumn( hwndCtrl, 0, szBuf, LVCFMT_LEFT, iFileNameWidth, 0); MLLoadString(IDS_LISTTITLE_FILESIZE, szBuf, MAX_PATH); ListCtrl_InsertColumn( hwndCtrl, 1, szBuf, LVCFMT_LEFT, nWidth * 3 / 10, 0); // insert dependent files into list box int iIndex = -1; LONG lResult = ERROR_SUCCESS; DWORD dwFileSize = 0; BOOL bOCXRemovable = IsModuleRemovable(GetStringInfo(pcpidl, SI_LOCATION)); for (UINT iFile = 0; iFile < cTotalFiles; iFile++) { if (!GetDependentFile(pcpidl, iFile, szBuf, &dwFileSize)) { Assert(FALSE); break; } // put a star after file name if file is not safe for removal if (!bOCXRemovable) { lstrcat(szBuf, TEXT("*")); } else if (!IsModuleRemovable(szBuf)) { // check if it is inf file. TCHAR szExt[10]; MLLoadString(IDS_EXTENSION_INF, szExt, 10); int nLen = lstrlen(szBuf); int nLenExt = lstrlen(szExt); if ((nLen > nLenExt) && (lstrcmpi(szBuf+(nLen-nLenExt), szExt) != 0)) lstrcat(szBuf, TEXT("*")); } PathCompactPath(NULL, szBuf, iFileNameWidth); iIndex = ListCtrl_InsertItem(hwndCtrl, LVIF_TEXT, iFile, szBuf, 0, 0, 0, 0); if (dwFileSize > 0) { TCHAR szBuf2[100]; wsprintf(szBuf2, "%u", dwFileSize); // insert commas to separate groups of digits int nLen = lstrlen(szBuf2); int i = 0, j = (nLen <= 3 ? nLen : (nLen % 3)); TCHAR *pCh = szBuf2 + j; for (; i < j; i++) szBuf[i] = szBuf2[i]; for (; *pCh != '\0'; i++, pCh++) { if (((pCh - szBuf2) % 3 == j) && (i > 0)) szBuf[i++] = ','; szBuf[i] = *pCh; } szBuf[i] = '\0'; } else MLLoadString(IDS_STATUS_DAMAGED, szBuf, MAX_PATH); ListCtrl_SetItemText(hwndCtrl, iIndex, 1, szBuf); } // insert columns into file list box hwndCtrl = GetDlgItem(hDlg, IDC_PACKAGELIST); Assert(::IsWindow(hwndCtrl)); GetClientRect(hwndCtrl, &rect); nWidth = (rect.right - rect.left) / 2; MLLoadString(IDS_LISTTITLE_PACKAGENAME, szBuf, MAX_PATH); ListCtrl_InsertColumn( hwndCtrl, 0, szBuf, LVCFMT_LEFT, nWidth, 0); MLLoadString(IDS_LISTTITLE_NAMESPACE, szBuf, MAX_PATH); ListCtrl_InsertColumn( hwndCtrl, 1, szBuf, LVCFMT_LEFT, nWidth, 0); // insert dependent packages into list box UINT cTotalPackages = 0;; if ( pcpidl->ci.dwIsDistUnit ) { CParseInf parseInf; if ( SUCCEEDED(parseInf.DoParseDU( GetStringInfo( pcpidl, SI_LOCATION), GetStringInfo( pcpidl,SI_CLSID ))) ) { CPackageNode *ppn; for ( ppn = parseInf.GetFirstPackage(); ppn != NULL; ppn = parseInf.GetNextPackage(), cTotalPackages++ ) { iIndex = ListCtrl_InsertItem(hwndCtrl, LVIF_TEXT, cTotalPackages, ppn->GetName(), 0, 0, 0, 0); ListCtrl_SetItemText(hwndCtrl, iIndex, 1, ppn->GetNamespace()); } } } // update description { TCHAR szMsg[MESSAGE_MAXSIZE]; TCHAR szBuf[MESSAGE_MAXSIZE]; // BUG: This is not the correct way to make va_list for Alpha DWORD_PTR adwArgs[3]; adwArgs[0] = cTotalFiles; adwArgs[1] = cTotalPackages; adwArgs[2] = (DWORD_PTR) GetStringInfo(pcpidl, SI_CONTROL); MLLoadString(IDS_MSG_DEPENDENCY, szBuf, MESSAGE_MAXSIZE); FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, szBuf, 0, 0, szMsg, MESSAGE_MAXSIZE, (va_list*)adwArgs ); SetDlgItemText(hDlg, IDC_STATIC_DESCRIPTION, szMsg); } } // Dialog proc for page 2 INT_PTR CALLBACK ControlItem_PropPage2Proc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE) GetWindowLongPtr(hDlg, DWLP_USER); LPCONTROLPIDL pcpidl = lpPropSheet ? (LPCONTROLPIDL)lpPropSheet->lParam : NULL; const static DWORD aIds[] = { IDC_DEPENDENCYLIST, IDH_DLOAD_FILE_DEP, IDC_PACKAGELIST, IDH_DLOAD_JAVAPKG_DEP, 0, 0 }; switch(message) { case WM_HELP: SHWinHelpOnDemandWrap((HWND)(((LPHELPINFO)lParam)->hItemHandle), "iexplore.hlp", HELP_WM_HELP, (DWORD_PTR)(LPSTR)aIds); break; case WM_CONTEXTMENU: SHWinHelpOnDemandWrap((HWND)wParam, "iexplore.hlp", HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID)aIds); break; case WM_INITDIALOG: InitPropPage2(hDlg, lParam); break; case WM_DESTROY: DestroyDialogIcon(hDlg); break; case WM_COMMAND: break; default: return FALSE; } // end of switch return TRUE; } #if 0 // Do UI update BOOL Page3_OnCommand(HWND hDlg, WORD wCmd) { HWND hwnd = GetDlgItem(hDlg, IDC_CHECK_NEVERUPDATE); Assert(hwnd != NULL); // if top check box is checked, disable the edit box BOOL bEnable = ((int)::SendMessage(hwnd, BM_GETCHECK, 0, 0) != 1); hwnd = GetDlgItem(hDlg, IDC_EDIT_UPDATEINTERVAL); Assert(hwnd != NULL); EnableWindow(hwnd, bEnable); // if top check box is not checked and edit box does not // have the focus and it is empty, put in default interval if (bEnable && (GetFocus() != hwnd)) { TCHAR szText[10]; if (GetWindowText(hwnd, szText, 10) == 0) { // wsprintf(szText, "%i", g_dwDefaultInterval); SetWindowText(hwnd, szText); } } return TRUE; } #endif /////////////////////////////////////////////////////////////////////////////// // functions that deal with property page 4 void InitPropPage4(HWND hDlg, LPARAM lParam) { SetWindowLongPtr(hDlg, DWLP_USER, lParam); LPCONTROLPIDL pcpidl = (LPCONTROLPIDL)((LPPROPSHEETPAGE)lParam)->lParam; LPTSTR lpszFileName = (LPTSTR)GetStringInfo(pcpidl, SI_LOCATION); TCHAR szBuf[MESSAGE_MAXSIZE]; DWORD dwHandle = 0, dwSizeVer = 0; LPTSTR lpBuffer = NULL; UINT uSize = 0; LPVOID lpVerData = NULL; UINT uLen = 0; DWORD dwLangCodePage = 0; char szQueryPrefix[MAX_QUERYPREFIX_LEN]; char szQueryString[MAX_QUERYSTRING_LEN]; // draw control icon { LPCTSTR pszIcon = GetStringInfo(pcpidl, SI_LOCATION); HICON hIcon = NULL; if (!pszIcon || !(hIcon = ExtractIcon(g_hInst, pszIcon, 0))) { hIcon = GetDefaultOCIcon( pcpidl ); } Assert(hIcon != NULL); SendDlgItemMessage(hDlg, IDC_STATIC_ICON, STM_SETICON, (WPARAM)hIcon, 0); } // set page header if (MLLoadString(IDS_VERSION_PAGE_HEADER, szBuf, MESSAGE_MAXSIZE)) { TCHAR szHeading[MESSAGE_MAXSIZE]; LPCTSTR pszControl = GetStringInfo(pcpidl, SI_CONTROL); if (pszControl) { wsprintf(szHeading, szBuf, pszControl); SetDlgItemText(hDlg, IDC_STATIC_VER_HEADING, szHeading); } } // set Version field LPCTSTR pszVersion = GetStringInfo(pcpidl, SI_VERSION); if (!pszVersion) return; SetDlgItemText(hDlg, IDC_STATIC_VER_VERSION, pszVersion); if (!lpszFileName) return; dwSizeVer = GetFileVersionInfoSize(lpszFileName, &dwHandle); if (dwSizeVer <= 0) return; BYTE *pbData = new BYTE[dwSizeVer]; if (pbData == NULL) return; if (GetFileVersionInfo(lpszFileName, 0, dwSizeVer, pbData)) { // Get correct codepage information if (!VerQueryValue(pbData, "\\VarFileInfo\\Translation", &lpVerData, &uLen)) { wsprintf(szQueryPrefix, "\\StringFileInfo\\%x\\CompanyName", DEFAULT_LANG_CODEPAGE_PAIR); } else { char szLangCodePad[9]; char szVBufPad[5], szVBuf[5]; // To fit a DWORD (padded) ASSERT(lpVerData); wnsprintf(szVBuf, ARRAYSIZE(szVBuf), "%x", LOWORD(*((DWORD *)lpVerData))); // Pad the low word to 4 digits lstrcpyn(szVBufPad, "0000", ARRAYSIZE(szVBufPad)); char *pszTmp = szVBufPad + (4 - lstrlen(szVBuf)); ASSERT(pszTmp > szVBufPad); lstrcpy(pszTmp, szVBuf); lstrcpyn(szLangCodePad, szVBufPad, ARRAYSIZE(szLangCodePad)); // Pad the high word to 4 digits wnsprintf(szVBuf, ARRAYSIZE(szVBuf), "%x", HIWORD(*((DWORD *)lpVerData))); lstrcpy(szVBufPad, "0000"); pszTmp = szVBufPad + (4 - lstrlen(szVBuf)); ASSERT(pszTmp > szVBufPad); lstrcpy(pszTmp, szVBuf); // Concatenate to get a codepage/lang-id string lstrcatn(szLangCodePad, szVBufPad, ARRAYSIZE(szLangCodePad)); lstrcpy(szQueryPrefix, "\\StringFileInfo\\"); lstrcat(szQueryPrefix, szLangCodePad); } // set Company field wnsprintf(szQueryString, ARRAYSIZE(szQueryString), "%s\\CompanyName", szQueryPrefix); if (VerQueryValue(pbData, szQueryString, (void **)&lpBuffer, &uSize)) SetDlgItemText(hDlg, IDC_STATIC_VER_COMPANY, lpBuffer); // set Description field wnsprintf(szQueryString, ARRAYSIZE(szQueryString), "%s\\FileDescription", szQueryPrefix); if (VerQueryValue(pbData, szQueryString, (void **)&lpBuffer, &uSize)) SetDlgItemText(hDlg, IDC_STATIC_VER_DESCRIPTION, lpBuffer); // set CopyRight field wnsprintf(szQueryString, ARRAYSIZE(szQueryString), "%s\\LegalCopyright", szQueryPrefix); if (VerQueryValue(pbData, szQueryString, (void **)&lpBuffer, &uSize)) SetDlgItemText(hDlg, IDC_STATIC_VER_COPYRIGHT, lpBuffer); // set Language field if (VerQueryValue(pbData, TEXT("\\VarFileInfo\\Translation"), (void **)&lpBuffer, &uSize)) { LPWORD lpLangId = (LPWORD)lpBuffer; VerLanguageName(*lpLangId, szBuf, MESSAGE_MAXSIZE); SetDlgItemText(hDlg, IDC_STATIC_VER_LANGUAGE, szBuf); } } delete [] pbData; } // Dialog proc for page 4 INT_PTR CALLBACK ControlItem_PropPage4Proc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE) GetWindowLongPtr(hDlg, DWLP_USER); LPCONTROLPIDL pcpidl = lpPropSheet ? (LPCONTROLPIDL)lpPropSheet->lParam : NULL; const static DWORD aIds[] = { IDC_STATIC_VER_LABEL_VERSION, IDH_DLOAD_VERSION, IDC_STATIC_VER_LABEL_DESCRIPTION, IDH_DLOAD_DESC, IDC_STATIC_VER_LABEL_COMPANY, IDH_DLOAD_COMPANY, IDC_STATIC_VER_LABEL_LANGUAGE, IDH_DLOAD_LANG, IDC_STATIC_VER_LABEL_COPYRIGHT, IDH_DLOAD_COPYRIGHT, IDC_STATIC_VER_VERSION, IDH_DLOAD_VERSION, IDC_STATIC_VER_DESCRIPTION, IDH_DLOAD_DESC, IDC_STATIC_VER_COMPANY, IDH_DLOAD_COMPANY, IDC_STATIC_VER_LANGUAGE, IDH_DLOAD_LANG, IDC_STATIC_VER_COPYRIGHT, IDH_DLOAD_COPYRIGHT, IDC_STATIC_CONTROL, IDH_DLOAD_OBJNAME, 0, 0 }; switch(message) { case WM_HELP: SHWinHelpOnDemandWrap((HWND)(((LPHELPINFO)lParam)->hItemHandle), "iexplore.hlp", HELP_WM_HELP, (DWORD_PTR)(LPSTR)aIds); break; case WM_CONTEXTMENU: SHWinHelpOnDemandWrap((HWND)wParam, "iexplore.hlp", HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID)aIds); break; case WM_INITDIALOG: InitPropPage4(hDlg, lParam); break; case WM_DESTROY: DestroyDialogIcon(hDlg); break; case WM_COMMAND: // user can't change anything, so we don't care about any messages break; default: return FALSE; } // end of switch return TRUE; } /////////////////////////////////////////////////////////////////////////////// // functions that deal with property dialog HRESULT CreatePropDialog(HWND hwnd, LPCONTROLPIDL pcpidl) { #ifdef AUTO_UPDATE PROPSHEETPAGE psp[NUM_PAGES] = {{0},{0},{0},{0}}; #else PROPSHEETPAGE psp[NUM_PAGES] = {{0},{0},{0}}; #endif PROPSHEETHEADER psh = {0}; // initialize propsheet page 1. psp[0].dwSize = sizeof(PROPSHEETPAGE); psp[0].dwFlags = 0; psp[0].hInstance = MLGetHinst(); psp[0].pszTemplate = MAKEINTRESOURCE(IDD_PROP_GENERAL); psp[0].pszIcon = NULL; psp[0].pfnDlgProc = ControlItem_PropPage1Proc; psp[0].pszTitle = NULL; psp[0].lParam = (LPARAM)pcpidl; // send it the cache entry struct // initialize propsheet page 2. psp[1].dwSize = sizeof(PROPSHEETPAGE); psp[1].dwFlags = 0; psp[1].hInstance = MLGetHinst(); psp[1].pszTemplate = MAKEINTRESOURCE(IDD_PROP_DEPENDENCY); psp[1].pszIcon = NULL; psp[1].pfnDlgProc = ControlItem_PropPage2Proc; psp[1].pszTitle = NULL; psp[1].lParam = (LPARAM)pcpidl; // send it the cache entry struct #ifdef AUTO_UPDATE // initialize propsheet page 3. psp[2].dwSize = sizeof(PROPSHEETPAGE); psp[2].dwFlags = 0; psp[2].hInstance = MLGetHinst(); psp[2].pszTemplate = MAKEINTRESOURCE(IDD_PROP_UPDATE); psp[2].pszIcon = NULL; psp[2].pfnDlgProc = ControlItem_PropPage3Proc; psp[2].pszTitle = NULL; psp[2].lParam = (LPARAM)pcpidl; // send it the cache entry struct #endif // initialize propsheet page 4. psp[NUM_PAGES-1].dwSize = sizeof(PROPSHEETPAGE); psp[NUM_PAGES-1].dwFlags = 0; psp[NUM_PAGES-1].hInstance = MLGetHinst(); psp[NUM_PAGES-1].pszTemplate = MAKEINTRESOURCE(IDD_PROP_VERSION); psp[NUM_PAGES-1].pszIcon = NULL; psp[NUM_PAGES-1].pfnDlgProc = ControlItem_PropPage4Proc; psp[NUM_PAGES-1].pszTitle = NULL; psp[NUM_PAGES-1].lParam = (LPARAM)pcpidl; // send it the cache entry struct // initialize propsheet header. psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPSHEETPAGE|PSH_NOAPPLYNOW|PSH_PROPTITLE; psh.hwndParent = hwnd; psh.pszCaption = GetStringInfo(pcpidl, SI_CONTROL); psh.nPages = NUM_PAGES; psh.nStartPage = 0; psh.ppsp = (LPCPROPSHEETPAGE)&psp; // invoke the property sheet PropertySheet(&psh); return NOERROR; }