APP-COMM-Capitel/setup/source.win/setup.c

3624 lines
115 KiB
C

#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <commctrl.h>
#include <setupapi.h>
#include <objbase.h>
#include <shlobj.h>
#include <objidl.h>
#include "setup.h"
#define REG_UNINSTALL_PATH \
"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
#define IS_WINNT (BOOL)(GetVersion() < 0x80000000)
#define IS_WIN2K (BOOL)((IS_WINNT) && (LOBYTE(LOWORD(GetVersion()))>4))
#define IS_WIN32S (BOOL)(!(IS_WINNT) && (LOBYTE(LOWORD(GetVersion()))<4))
#define IS_WIN95 (BOOL)(!(IS_WINNT) && !(IS_WIN32S))
#define WM_USER_STEP WM_USER+10
#define WM_USER_PROGRESS WM_USER+11
#define WM_USER_RESULT WM_USER+12
#define SLBN_CHECKING 0xFFF0
#define SLBN_CHECKED 0xFFF1
#define WATERMARK_TOTAL_SIZE_X 503
#define WATERMARK_TOTAL_SIZE_Y 313
#define WATERMARK_IMAGE_OFFS_X 0
#define WATERMARK_IMAGE_OFFS_Y 0
#define HEADER_TOTAL_SIZE_X 503
#define HEADER_TOTAL_SIZE_Y 58
#define HEADER_IMAGE_OFFS_X 443
#define HEADER_IMAGE_OFFS_Y 5
#define PSH_WIZARD_LITE 0x00400000
#define PSH_NOCONTEXTHELP 0x02000000
typedef struct sWizardData
{
HINF hInf;
char cInfName[MAX_PATH];
int iInfErrorLine;
HIMAGELIST hImgLst;
HFONT hWelcomeTitleFont;
HFONT hHeaderTitleFont;
HICON hSmInfoIcon;
HICON hSmAlertIcon;
char cWelcomeTitle[256];
char cWelcomeText[1024];
char cPage2HdrTitle[256];
char cPage2HdrSubTitle[256];
char cPage3HdrTitle[256];
char cPage3HdrSubTitle[256];
char cPage4HdrTitle[256];
char cPage4HdrSubTitle[256];
}
tWizardData;
/* ------------------------------------------------------------------------
* Lokale Funktionstypen
* ------------------------------------------------------------------------ */
int PreviousInstance(void);
HWND CreateMainWindow(HINSTANCE hInstance, int nCmdShow);
int SetupWizard(HWND hwndOwner);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WizPage1Proc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WizPage2Proc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WizPage3Proc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WizPage4Proc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WizPage5Proc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WizPage6Proc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WizPage7Proc(HWND, UINT, WPARAM, LPARAM);
DWORD WINAPI InstallThread(void* p);
DWORD WINAPI RemoveThread(void* p);
void InitPlatformSectionNames(HINF hInf);
int InitProductSelection(HWND hwnd, HINF hInf);
int BuildProductList(HWND hwnd, HINF hInf, char* ProductList);
int BuildInstallSectionList(HINF hInf, char* ProdList, char* SectList);
int BuildRemoveSectionList(HINF hInf, char* ProdList, char* SectList);
int CheckProductsForFlag(HINF hInf, char* ProdList, int Flag);
void GetProductDescription(HINF hInf, int ProdIdx, char* Buff, int szBuff);
int GetProductVersionDiff(HINF hInf, int ProdIdx);
int GetUninstallProductName(HINF hInf, char* ProdList,
char* Name, int cbName, int* pIconIdx);
int GetLastUserDir(HINF hInf, char* ProdList, char* Path);
int CreateUninstallEntrys(HINF hInf, char* ProdList);
int RemoveUninstallEntrys(HINF hInf, char* ProdList);
int InstallMultipleSections(HINF hInf, char* Sections, HWND hwnd);
UINT WINAPI QueueCallback(PVOID, UINT, UINT, UINT);
int StopServices(HINF hInf, char* Section);
int StartServices(HINF hInf, char* Section);
int InstallServices(HINF hInf, char* Section);
int DoStopService(char* SvcName);
int DoAddService(HINF hInf, char* SvcName, char* SvcSect);
int DoDelService(char* SvcName);
int DoStartService(char* SvcName);
int AddServiceToGroupOrder(HINF hInf, char* SvcSection);
int UpdateShortcuts(HINF hInf, char* Section);
int CreateShortcut(char* Where, char* Title,
char* Exe, char* Args, char* Ico, int IcoIdx, int Flags);
int DeleteShortcut(char* Where, char* Title);
int DoExecStatements(HINF hInf, char* Section, int Step, HWND hwndOwner);
int ExecuteCommand(char* Cmd, char* Arg, char* WorkDir, int Flags, HWND hwndOwner);
int GetDefaultTargetPath(HINF hInf, char* Path, char* RelPath);
int QueryTargetPath(HWND hwnd, char* Path, char* RelPath);
int QueryApplPath(char* Path);
int QueryStartMenuProgramFolder(char* Path, char* Where);
int QuerySetupExePath(HINF hInf, char* Section, char* Path);
int GetFileCount(char* Path);
int DelayFileDelete(char* File);
int DelayDirDelete(char* Dir);
int CenterWindow(HWND hwndChild, HWND hwndParent);
LANGID GetDefaultLanguage(char* ResourceID);
char* GetMultiString(const char* c, int index);
int InsertMultiString(char* c, char* s, int index);
int RemoveMultiString(char* c, int index);
int CountMultiStrings(const char* c);
int FindMultiString(const char* c, const char* s);
int GetMultiStringLength(const char* c);
int GetComCtlVersion(DWORD* pMajor, DWORD* pMinor);
int ErrorMessageBox(HWND hwndOwner, char* pText, int iErrCode);
HBITMAP MakeWizardBmp(HWND hwnd, HBITMAP hBmpOrg,
int iSizeX, int iSizeY, int iOffsX, int iOffsY);
int InitWizardData(HINSTANCE hInstance, tWizardData* pData);
int FreeWizardData(tWizardData* pData);
DLGTEMPLATE* LoadDlgTemplate(HINSTANCE hInstance, char* pszTemplate);
void FreeDlgTemplate(DLGTEMPLATE* pDlgTemplate);
/* ------------------------------------------------------------------------
* Lokale Variablen
* ------------------------------------------------------------------------ */
static int Remove = 0;
static int Reboot = 0;
static int DisableUI = 0;
static int CatchReboot = 0;
static LANGID AppLang = 0;
static char* InstallSect = 0;
static char* RemoveSect = 0;
static char* ProductSect = 0;
static char ProductList[1024] = "";
static char SectionList[1024] = "";
static char UserTargetDir[MAX_PATH] = "";
static int iWizStyle = 0;
static WNDPROC oldSelectLBproc;
/* ------------------------------------------------------------------------
* $Func WinMain
* Funktion: WinMain
* Aufgabe.: Main-Entrypoint, erstellt hauptfenster und bearbeitet msg-loop
* Resultat: Exit-Code des programms
* Hinweis.:
* ------------------------------------------------------------------------ */
int APIENTRY WinMain(HINSTANCE hInstance, /* instance-handle */
HINSTANCE hPrevInst, /* obsolet unter win32 */
LPSTR pCmdLine, /* zeiger auf kommandozeile */
int nCmdShow /* show-befehl */
)
{
MSG msg;
char* Arg;
HWND hwndMain;
DEVMODE sDispMode;
char Path[MAX_PATH];
DWORD vMajor, vMinor;
if(PreviousInstance()) return 0;
AppLang = GetDefaultLanguage(MAKEINTRESOURCE(IDD_WIZPAGE1));
InitCommonControls();
if(GetComCtlVersion(&vMajor,&vMinor))
{
if(vMajor > 4 || (vMajor == 4 && vMinor >= 71)) iWizStyle = 1;
// if(vMajor > 5 || (vMajor == 5 && vMinor >= 80)) iWizStyle = 2;
}
if(EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&sDispMode) &&
sDispMode.dmBitsPerPel == 4 && IS_WIN95) iWizStyle = 0;
Arg = strtok(pCmdLine," ");
while(Arg)
{
if(!strnicmp(Arg,"/quiet",6)) DisableUI = 1;
if(!strnicmp(Arg,"/style:",7)) iWizStyle = atoi(Arg+7);
if(!strnicmp(Arg,"/install",8)) Remove = 0;
if(!strnicmp(Arg,"/install:",9))
strcpy(ProductList,Arg+9), ProductList[strlen(ProductList)+1] = 0;
if(!strnicmp(Arg,"/remove",7)) Remove = 1;
if(!strnicmp(Arg,"/remove:",8))
strcpy(ProductList,Arg+8), ProductList[strlen(ProductList)+1] = 0;
if(!strnicmp(Arg,"/lang:eng",9))
AppLang = MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US);
if(!strnicmp(Arg,"/lang:ger",9))
AppLang = MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN);
if(!strnicmp(Arg,"/lang:fre",9))
AppLang = MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH);
if(!strnicmp(Arg,"/lang:ita",9))
AppLang = MAKELANGID(LANG_ITALIAN,SUBLANG_ITALIAN);
if(!strnicmp(Arg,"/lang:spa",9))
AppLang = MAKELANGID(LANG_SPANISH,SUBLANG_NEUTRAL);
if(!strnicmp(Arg,"/lang:dut",9))
AppLang = MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH);
Arg = strtok(0," ");
}
if(IS_WINNT) SetThreadLocale(MAKELCID(AppLang,SORT_DEFAULT));
GetModuleFileName(0, Path, sizeof(Path));
if(strrchr(Path,'\\')) strrchr(Path,'\\')[0] = 0;
SetCurrentDirectory(Path);
hwndMain = CreateMainWindow(hInstance, nCmdShow);
if(!hwndMain) return 0;
while(GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func PreviousInstance
* Funktion: PreviousInstance
* Aufgabe.: ueberpruefen, ob es schon eine instanz von uns gibt
* Resultat: TRUE, wenn andere instanz gefunden, sonst FALSE
* Hinweis.: aktiviert das fenster einer evtl. gefundenen instanz
* ------------------------------------------------------------------------ */
int PreviousInstance(void)
{
HWND hwnd;
char buff[256];
char* c = buff;
GetModuleFileName(0, buff, sizeof(buff));
while(*c) *c = tolower(*c == '\\' ? '_' : *c), c++;
CreateMutex(0, 1, buff);
if(GetLastError() != ERROR_ALREADY_EXISTS) return 0;
hwnd = FindWindow(APPNAME, 0);
if(hwnd)
{
if(IsIconic(hwnd)) ShowWindow(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func CreateMainWindow
* Funktion: CreateMainWindow
* Aufgabe.: registriert unsere fensterklasse und erstellt das hauptfenster
* Resultat: window-handle des hauptfensters
* Hinweis.:
* ------------------------------------------------------------------------ */
HWND CreateMainWindow(HINSTANCE hInstance, /* unser instance-handle */
int nCmdShow /* show-befehl von WinMain() */
)
{
WNDCLASS wc;
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ID_ICON));
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = 0;
wc.lpszClassName = APPNAME;
if(!RegisterClass(&wc)) return 0;
return CreateWindow(APPNAME, "", 0, 0, 0, 100, 100, 0, 0, hInstance, 0);
}
/* ------------------------------------------------------------------------
* $Func WndProc
* Funktion: WndProc
* Aufgabe.: fensterprozedur des hauptfensters
* Resultat: abhaengig von der zu bearbeitenden message
* Hinweis.:
* ------------------------------------------------------------------------ */
LRESULT CALLBACK WndProc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam /* zweiter message-parameter */
)
{
switch(message)
{
case WM_CREATE:
SetupWizard(hwnd);
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
case WM_QUERYENDSESSION:
if(!CatchReboot) return 1;
Reboot = 1;
return 0;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
/* ------------------------------------------------------------------------
* $Func SetupWizard
* Funktion: SetupWizard
* Aufgabe.: zeigt den eigentlichen setup-wizard an
* Resultat: abhaengig von der zu bearbeitenden message
* Hinweis.:
* ------------------------------------------------------------------------ */
int SetupWizard(HWND hwnd) /* fensterhandle */
{
unsigned int iHlp;
HINSTANCE hInstance;
HBITMAP hBmp1, hBmp2;
tWizardData sData = {0};
PROPSHEETPAGE sPage = {0};
PROPSHEETHEADER sHdr = {0};
DLGTEMPLATE* apDlgRes[7] = {0};
HPROPSHEETPAGE ahPages[7] = {0};
char cInfName[MAX_PATH], cTxt[256], cFmt[256];
hInstance = (HANDLE)GetWindowLong(hwnd, GWL_HINSTANCE);
GetModuleFileName(0, cInfName, sizeof(cInfName));
if(strrchr(cInfName,'\\')) strrchr(cInfName,'\\')[1] = 0;
strcat(cInfName, INFNAME);
sData.hInf = SetupOpenInfFile(cInfName, 0, INF_STYLE_WIN4, &iHlp);
if(sData.hInf == INVALID_HANDLE_VALUE)
{
LoadString(hInstance, STR_INFERROR, cFmt, sizeof(cFmt));
sprintf(cTxt, cFmt, cInfName, iHlp);
MessageBox(hwnd, cTxt, 0, MB_OK|MB_ICONERROR);
return 0;
}
InitPlatformSectionNames(sData.hInf);
InitWizardData(hInstance, &sData);
sHdr.dwSize = iWizStyle ? sizeof(sHdr) : PROPSHEETHEADER_V1_SIZE;
sHdr.dwFlags = 0;
sHdr.hwndParent = hwnd;
sHdr.hInstance = hInstance;
sHdr.nStartPage = Remove ? 5 : 0;
sHdr.phpage = ahPages;
sPage.dwSize = iWizStyle ? sizeof(sPage) : PROPSHEETPAGE_V1_SIZE;
sPage.hInstance = hInstance;
sPage.lParam = (LPARAM)&sData;
sPage.dwFlags = PSP_DLGINDIRECT|(iWizStyle?PSP_HIDEHEADER:0);
sPage.pfnDlgProc = WizPage1Proc;
sPage.pResource = apDlgRes[sHdr.nPages] = LoadDlgTemplate(hInstance,
MAKEINTRESOURCE(iWizStyle?IDD_WIZ97PAGE1:IDD_WIZPAGE1));
sHdr.phpage[sHdr.nPages++] = CreatePropertySheetPage(&sPage);
sPage.dwFlags = PSP_DLGINDIRECT|(iWizStyle?PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE:0);
sPage.pfnDlgProc = WizPage2Proc;
sPage.pszHeaderTitle = sData.cPage2HdrTitle;
sPage.pszHeaderSubTitle = sData.cPage2HdrSubTitle;
sPage.pResource = apDlgRes[sHdr.nPages] = LoadDlgTemplate(hInstance,
MAKEINTRESOURCE(iWizStyle?IDD_WIZ97PAGE2:IDD_WIZPAGE2));
sHdr.phpage[sHdr.nPages++] = CreatePropertySheetPage(&sPage);
sPage.dwFlags = PSP_DLGINDIRECT|(iWizStyle?PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE:0);
sPage.pfnDlgProc = WizPage3Proc;
sPage.pszHeaderTitle = sData.cPage3HdrTitle;
sPage.pszHeaderSubTitle = sData.cPage3HdrSubTitle;
sPage.pResource = apDlgRes[sHdr.nPages] = LoadDlgTemplate(hInstance,
MAKEINTRESOURCE(iWizStyle?IDD_WIZ97PAGE3:IDD_WIZPAGE3));
sHdr.phpage[sHdr.nPages++] = CreatePropertySheetPage(&sPage);
sPage.dwFlags = PSP_DLGINDIRECT|(iWizStyle?PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE:0);
sPage.pfnDlgProc = WizPage4Proc;
sPage.pszHeaderTitle = sData.cPage4HdrTitle;
sPage.pszHeaderSubTitle = sData.cPage4HdrSubTitle;
sPage.pResource = apDlgRes[sHdr.nPages] = LoadDlgTemplate(hInstance,
MAKEINTRESOURCE(iWizStyle?IDD_WIZ97PAGE4:IDD_WIZPAGE4));
sHdr.phpage[sHdr.nPages++] = CreatePropertySheetPage(&sPage);
sPage.dwFlags = PSP_DLGINDIRECT|(iWizStyle?PSP_HIDEHEADER:0);
sPage.pfnDlgProc = WizPage5Proc;
sPage.pResource = apDlgRes[sHdr.nPages] = LoadDlgTemplate(hInstance,
MAKEINTRESOURCE(iWizStyle?IDD_WIZ97PAGE5:IDD_WIZPAGE5));
sHdr.phpage[sHdr.nPages++] = CreatePropertySheetPage(&sPage);
sPage.dwFlags = PSP_DLGINDIRECT|(iWizStyle?PSP_HIDEHEADER:0);
sPage.pfnDlgProc = WizPage6Proc;
sPage.pResource = apDlgRes[sHdr.nPages] = LoadDlgTemplate(hInstance,
MAKEINTRESOURCE(iWizStyle?IDD_WIZ97PAGE6:IDD_WIZPAGE6));
sHdr.phpage[sHdr.nPages++] = CreatePropertySheetPage(&sPage);
sPage.dwFlags = PSP_DLGINDIRECT|(iWizStyle?PSP_HIDEHEADER:0);
sPage.pfnDlgProc = WizPage7Proc;
sPage.pResource = apDlgRes[sHdr.nPages] = LoadDlgTemplate(hInstance,
MAKEINTRESOURCE(iWizStyle?IDD_WIZ97PAGE7:IDD_WIZPAGE7));
sHdr.phpage[sHdr.nPages++] = CreatePropertySheetPage(&sPage);
if(iWizStyle == 0)
{
sHdr.dwFlags |= PSH_WIZARD;
}
else if(iWizStyle == 1)
{
sHdr.dwFlags |= PSH_WIZARD97|PSH_WATERMARK|PSH_HEADER|
PSH_USEHBMWATERMARK|PSH_USEHBMHEADER|PSH_STRETCHWATERMARK;
hBmp1 = LoadBitmap(hInstance, MAKEINTRESOURCE(ID_WATERMARK));
hBmp2 = LoadBitmap(hInstance, MAKEINTRESOURCE(ID_HEADER));
sHdr.hbmWatermark = MakeWizardBmp(hwnd, hBmp1, WATERMARK_TOTAL_SIZE_X,
WATERMARK_TOTAL_SIZE_Y, WATERMARK_IMAGE_OFFS_X, WATERMARK_IMAGE_OFFS_Y);
sHdr.hbmHeader = MakeWizardBmp(hwnd, hBmp2, HEADER_TOTAL_SIZE_X,
HEADER_TOTAL_SIZE_Y, HEADER_IMAGE_OFFS_X, HEADER_IMAGE_OFFS_Y);
DeleteObject(hBmp1);
DeleteObject(hBmp2);
}
else if(iWizStyle == 2)
{
sHdr.dwFlags |= PSH_WIZARD97|PSH_WATERMARK|PSH_HEADER;
sHdr.pszbmWatermark = MAKEINTRESOURCE(ID_WATERMARK);
sHdr.pszbmHeader = MAKEINTRESOURCE(ID_HEADER);
}
PropertySheet(&sHdr);
if(Reboot) SetupPromptReboot(0, hwnd, 0);
SetupCloseInfFile(sData.hInf);
FreeWizardData(&sData);
while(sHdr.nPages--) FreeDlgTemplate(apDlgRes[sHdr.nPages]);
return 1;
}
/* ------------------------------------------------------------------------
* $Func WizPage1Proc
* Funktion: WizPage1Proc
* Aufgabe.: fensterprozedur der ersten wizard-propertsheet-page
* Resultat: abhaengig von der zu bearbeitenden message
* Hinweis.:
* ------------------------------------------------------------------------ */
LRESULT CALLBACK WizPage1Proc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam /* zweiter message-parameter */
)
{
switch(message)
{
case WM_INITDIALOG:
{
tWizardData* pData;
pData = (tWizardData*)((PROPSHEETPAGE*)lParam)->lParam;
SendDlgItemMessage(hwnd, IDC_TEXT1, WM_SETFONT,
(WPARAM)pData->hWelcomeTitleFont, 0);
SetDlgItemText(hwnd, IDC_TEXT1, pData->cWelcomeTitle);
SetDlgItemText(hwnd, IDC_TEXT2, pData->cWelcomeText);
CenterWindow(GetParent(hwnd), GetDesktopWindow());
return 1;
}
case WM_NOTIFY:
if(((NMHDR*)lParam)->code == PSN_SETACTIVE)
{
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT);
if(DisableUI) SetWindowLong(hwnd, DWL_MSGRESULT, -1);
}
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func SelectLBIsItemChecked
* Funktion: SelectLBIsItemChecked
* Aufgabe.: prueft, ob ein item in der select-listbox gecheckt ist
* Resultat: TRUE wenn selektiert, sonst FALSE
* Hinweis.:
* ------------------------------------------------------------------------ */
int SelectLBIsItemChecked(HWND hwnd,
int iItemIdx)
{
int iItemData;
iItemData = SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)iItemIdx, 0);
if(iItemData == LB_ERR) return 0;
return LOWORD(iItemData);
}
/* ------------------------------------------------------------------------
* $Func SelectLBIsItemPale
* Funktion: SelectLBIsItemPale
* Aufgabe.: prueft, ob ein item 'blass' bzw. disabled ist
* Resultat: TRUE wenn erfolgreich, sonst FALSE
* Hinweis.:
* ------------------------------------------------------------------------ */
int SelectLBIsItemPale(HWND hwnd,
int iItemIdx)
{
int iItemData;
iItemData = SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)iItemIdx, 0);
if(iItemData == LB_ERR) return 0;
return HIBYTE(HIWORD(iItemData));
}
/* ------------------------------------------------------------------------
* $Func SelectLBCheckItem
* Funktion: SelectLBCheckItem
* Aufgabe.: checkt oder ent-checkt ein item in der select-listbox
* Resultat: TRUE wenn erfolgreich, sonst FALSE
* Hinweis.:
* ------------------------------------------------------------------------ */
int SelectLBCheckItem(HWND hwnd,
int iItemIdx,
int iCheckState)
{
int iItemData;
RECT sItemRect;
iItemData = SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)iItemIdx, 0);
if(iItemData == LB_ERR) return 0;
iItemData = MAKELONG(iCheckState, HIWORD(iItemData));
SendMessage(hwnd, LB_SETITEMDATA, (WPARAM)iItemIdx, (LPARAM)iItemData);
SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)iItemIdx, (LPARAM)&sItemRect);
InvalidateRect(hwnd, &sItemRect, 0);
SendMessage(GetParent(hwnd), WM_COMMAND,
MAKEWPARAM(GetWindowLong(hwnd,GWL_ID),SLBN_CHECKED),
MAKELPARAM(iItemIdx,LOWORD(iItemData)));
return 1;
}
/* ------------------------------------------------------------------------
* $Func SelectLBSetImage
* Funktion: SelectLBSetImage
* Aufgabe.: legt den index des icons fuer einen eintrag fest
* Resultat: TRUE wenn erfolgreich, sonst FALSE
* Hinweis.:
* ------------------------------------------------------------------------ */
int SelectLBSetImage(HWND hwnd,
int iItemIdx,
int iImageIdx,
int iPale)
{
int iItemData;
RECT sItemRect;
iItemData = SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)iItemIdx, 0);
if(iItemData == LB_ERR) return 0;
iItemData = MAKELONG(LOWORD(iItemData),MAKEWORD(iImageIdx,iPale));
SendMessage(hwnd, LB_SETITEMDATA, (WPARAM)iItemIdx, (LPARAM)iItemData);
SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)iItemIdx, (LPARAM)&sItemRect);
InvalidateRect(hwnd, &sItemRect, 0);
return 1;
}
/* ------------------------------------------------------------------------
* $Func SelectLBproc
* Funktion: SelectLBproc
* Aufgabe.: fensterprozedur fuer die select-listbox
* Resultat: abhaengig von der zu bearbeitenden message
* Hinweis.:
* ------------------------------------------------------------------------ */
LRESULT CALLBACK SelectLBproc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam /* zweiter message-parameter */
)
{
switch(message)
{
case WM_LBUTTONUP:
{
POINT pt;
RECT rect;
int iItemIdx, iCheckState;
pt.x = LOWORD(lParam); pt.y = HIWORD(lParam);
MapWindowPoints(hwnd, 0, &pt, 1);
iItemIdx = LBItemFromPt(hwnd, pt, 0);
if(iItemIdx < 0) break;
SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)iItemIdx, (LPARAM)&rect);
rect.right = rect.left + rect.bottom - rect.top;
pt.x = LOWORD(lParam); pt.y = HIWORD(lParam);
if(!PtInRect(&rect,pt)) break;
iCheckState = !SelectLBIsItemChecked(hwnd, iItemIdx);
SetWindowLong(GetParent(hwnd), DWL_MSGRESULT, 0);
SendMessage(GetParent(hwnd), WM_COMMAND,
MAKEWPARAM(GetWindowLong(hwnd,GWL_ID),SLBN_CHECKING),
MAKELPARAM(iItemIdx,iCheckState));
if(!GetWindowLong(GetParent(hwnd),DWL_MSGRESULT))
SelectLBCheckItem(hwnd, iItemIdx, iCheckState);
break;
}
case WM_KEYDOWN:
{
int iItemIdx, iCheckState;
if((char)wParam != VK_SPACE) break;
iItemIdx = SendMessage(hwnd, LB_GETCURSEL, 0, 0);
if(iItemIdx < 0) break;
iCheckState = !SelectLBIsItemChecked(hwnd, iItemIdx);
SetWindowLong(GetParent(hwnd), DWL_MSGRESULT, 0);
SendMessage(GetParent(hwnd), WM_COMMAND,
MAKEWPARAM(GetWindowLong(hwnd,GWL_ID),SLBN_CHECKING),
MAKELPARAM(iItemIdx,iCheckState));
if(!GetWindowLong(GetParent(hwnd),DWL_MSGRESULT))
SelectLBCheckItem(hwnd, iItemIdx, iCheckState);
break;
}
}
return CallWindowProc(oldSelectLBproc, hwnd, message, wParam, lParam);
}
/* ------------------------------------------------------------------------
* $Func WizPage2Proc
* Funktion: WizPage2Proc
* Aufgabe.: fensterprozedur der zweiten wizard-propertsheet-page
* Resultat: abhaengig von der zu bearbeitenden message
* Hinweis.:
* ------------------------------------------------------------------------ */
LRESULT CALLBACK WizPage2Proc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam) /* zweiter message-parameter */
{
tWizardData* pData = (tWizardData*)GetWindowLong(hwnd, DWL_USER);
switch(message)
{
case WM_INITDIALOG:
pData = (tWizardData*)((PROPSHEETPAGE*)lParam)->lParam;
SendDlgItemMessage(hwnd, IDC_HDR_TITLE, WM_SETFONT,
(WPARAM)pData->hHeaderTitleFont, 0);
SetDlgItemText(hwnd, IDC_HDR_TITLE, pData->cPage2HdrTitle);
SetDlgItemText(hwnd, IDC_HDR_SUBTITLE, pData->cPage2HdrSubTitle);
if(!strlen(ProductList) && InitProductSelection(hwnd,pData->hInf))
SetWindowLong(hwnd, DWL_USER, (LONG)pData);
oldSelectLBproc = (WNDPROC)SetWindowLong(
GetDlgItem(hwnd,IDC_PRODLIST), GWL_WNDPROC, (ULONG)SelectLBproc);
SendDlgItemMessage(hwnd, IDC_PRODLIST, LB_SETCURSEL, 0, 0);
SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_PRODLIST,LBN_SELCHANGE), 0);
return 1;
case WM_NOTIFY:
if(((NMHDR*)lParam)->code == PSN_KILLACTIVE)
{
BuildProductList(hwnd, pData->hInf, ProductList);
}
else if(((NMHDR*)lParam)->code == PSN_SETACTIVE)
{
if(!pData)
SetWindowLong(hwnd, DWL_MSGRESULT, -1);
else
{
SendMessage(hwnd, WM_COMMAND,
MAKEWPARAM(IDC_PRODLIST,SLBN_CHECKED), 0);
if(DisableUI)
{
SetWindowLong(hwnd, DWL_MSGRESULT, -1),
BuildProductList(hwnd, pData->hInf, ProductList);
}
}
}
return 1;
case WM_COMMAND:
if(LOWORD(wParam) == IDC_PRODLIST && HIWORD(wParam) == SLBN_CHECKING)
{
HINSTANCE hInstance;
char cProd[256], cFmt[256], cText[256], cTitle[256];
hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
SendDlgItemMessage(hwnd, IDC_PRODLIST,
LB_GETTEXT, (WPARAM)LOWORD(lParam), (LPARAM)cProd);
LoadString(hInstance, STR_WARNING, cTitle, sizeof(cTitle));
LoadString(hInstance, STR_VERSIONWARNING, cFmt, sizeof(cFmt));
sprintf(cText, cFmt, cProd);
if(HIWORD(lParam) &&
SelectLBIsItemPale(GetDlgItem(hwnd,IDC_PRODLIST),LOWORD(lParam)) &&
MessageBox(hwnd,cText,cTitle,MB_YESNO|MB_DEFBUTTON2|MB_ICONWARNING) != IDYES)
SetWindowLong(hwnd, DWL_MSGRESULT, 1);
}
else if(LOWORD(wParam) == IDC_PRODLIST && HIWORD(wParam) == SLBN_CHECKED)
{
int Idx, Cnt, SelCnt;
Cnt = SendDlgItemMessage(hwnd, IDC_PRODLIST, LB_GETCOUNT, 0, 0);
for(Idx = 0, SelCnt = 0; Idx < Cnt; Idx++)
if(SelectLBIsItemChecked(GetDlgItem(hwnd,IDC_PRODLIST),Idx))
SelCnt++;
PropSheet_SetWizButtons(GetParent(hwnd),
PSWIZB_BACK|(SelCnt?PSWIZB_NEXT:0));
}
else if(LOWORD(wParam) == IDC_PRODLIST && HIWORD(wParam) == LBN_SELCHANGE)
{
char Buff[1024];
int Idx = SendDlgItemMessage(hwnd, IDC_PRODLIST, LB_GETCURSEL, 0, 0);
if(Idx >= 0)
GetProductDescription(pData->hInf, Idx, Buff, sizeof(Buff)),
SetDlgItemText(hwnd, IDC_TEXT1, Buff);
}
return 1;
case WM_MEASUREITEM:
if((int)wParam == IDC_PRODLIST)
{
int cxImg, cyImg;
HIMAGELIST hImgLst;
HINSTANCE hInstance;
MEASUREITEMSTRUCT* pMeas;
pMeas = (MEASUREITEMSTRUCT*)lParam;
hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
hImgLst = ImageList_LoadBitmap(hInstance,
MAKEINTRESOURCE(ID_BMPLIST), 16, 0, 0x00808000);
SetWindowLong(GetDlgItem(hwnd,IDC_PRODLIST),
GWL_USERDATA, (LONG)hImgLst);
ImageList_GetIconSize(hImgLst, &cxImg, &cyImg);
pMeas->itemHeight = cyImg+2;
}
return 1;
case WM_DRAWITEM:
if((int)wParam == IDC_PRODLIST)
{
RECT rcTxt;
char aTxt[256];
HIMAGELIST hImgLst;
COLORREF col1, col2;
int cxImg, cyImg, fSel, fHlt, fPale, iImgIdx;
DRAWITEMSTRUCT* pDrw = (DRAWITEMSTRUCT*)lParam;
fSel = LOWORD(pDrw->itemData);
fPale = HIBYTE(HIWORD(pDrw->itemData));
iImgIdx = LOBYTE(HIWORD(pDrw->itemData));
fHlt = pDrw->itemState & ODS_SELECTED && pDrw->itemState & ODS_FOCUS;
hImgLst = (HIMAGELIST)
GetWindowLong(GetDlgItem(hwnd,IDC_PRODLIST), GWL_USERDATA);
FillRect(pDrw->hDC, &pDrw->rcItem,
(HBRUSH)(fHlt ? (COLOR_HIGHLIGHT+1) : (COLOR_WINDOW+1)));
if(pDrw->itemID >= 0)
{
ImageList_GetIconSize(hImgLst, &cxImg, &cyImg);
ImageList_Draw(hImgLst, fSel ? 14 : 15, pDrw->hDC,
pDrw->rcItem.left+1, pDrw->rcItem.top+1, ILD_TRANSPARENT);
ImageList_DrawEx(hImgLst, iImgIdx + 1, pDrw->hDC,
pDrw->rcItem.left + cyImg + 1, pDrw->rcItem.top + 1, 0, 0, 0,
(fHlt ? GetSysColor(COLOR_HIGHLIGHT) : GetSysColor(COLOR_WINDOW)),
ILD_TRANSPARENT|(fPale ? ILD_BLEND50 : 0));
SendDlgItemMessage(hwnd, IDC_PRODLIST,
LB_GETTEXT, (WPARAM)pDrw->itemID, (LPARAM)aTxt);
rcTxt.left = pDrw->rcItem.left + 2*cyImg + 4;
rcTxt.top = pDrw->rcItem.top + 1;
rcTxt.right = pDrw->rcItem.right - 1;
rcTxt.bottom = pDrw->rcItem.bottom - 1;
if(fPale)
col1 = SetTextColor(pDrw->hDC, GetSysColor(COLOR_GRAYTEXT));
else if(fHlt)
col1 = SetTextColor(pDrw->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
if(fHlt)
col2 = SetBkColor(pDrw->hDC,GetSysColor(COLOR_HIGHLIGHT));
DrawText(pDrw->hDC, aTxt, -1, &rcTxt, DT_VCENTER|DT_SINGLELINE);
if(fPale || fHlt)
SetTextColor(pDrw->hDC,col1);
if(fHlt)
SetBkColor(pDrw->hDC,col2);
}
if(pDrw->itemState & ODS_FOCUS) DrawFocusRect(pDrw->hDC,&pDrw->rcItem);
}
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func WizPage3Proc
* Funktion: WizPage3Proc
* Aufgabe.: fensterprozedur der dritten wizard-propertsheet-page
* Resultat: abhaengig von der zu bearbeitenden message
* Hinweis.:
* ------------------------------------------------------------------------ */
LRESULT CALLBACK WizPage3Proc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam) /* zweiter message-parameter */
{
tWizardData* pData = (tWizardData*)GetWindowLong(hwnd, DWL_USER);
switch(message)
{
case WM_INITDIALOG:
{
char cPath[MAX_PATH];
pData = (tWizardData*)((PROPSHEETPAGE*)lParam)->lParam;
SendDlgItemMessage(hwnd, IDC_HDR_TITLE, WM_SETFONT,
(WPARAM)pData->hHeaderTitleFont, 0);
SetDlgItemText(hwnd, IDC_HDR_TITLE, pData->cPage3HdrTitle);
SetDlgItemText(hwnd, IDC_HDR_SUBTITLE, pData->cPage3HdrSubTitle);
SetWindowLong(hwnd, DWL_USER, (LONG)pData);
if(!GetLastUserDir(pData->hInf,0,cPath))
GetDefaultTargetPath(pData->hInf, cPath, 0);
SetDlgItemText(hwnd, IDC_TARGETDIR, cPath);
return 1;
}
case WM_NOTIFY:
if(((NMHDR*)lParam)->code == PSN_SETACTIVE)
{
SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_TARGETDIR,EN_CHANGE), 0);
if(DisableUI) SetWindowLong(hwnd, DWL_MSGRESULT, -1);
}
return 1;
case WM_COMMAND:
if(LOWORD(wParam) == IDC_TARGETDIR && HIWORD(wParam) == EN_CHANGE)
{
int iResult;
GetDlgItemText(hwnd, IDC_TARGETDIR,
UserTargetDir, sizeof(UserTargetDir));
iResult = SetupSetDirectoryId(pData->hInf, DIRID_USER, UserTargetDir);
PropSheet_SetWizButtons(GetParent(hwnd),
iResult ? (PSWIZB_BACK|PSWIZB_NEXT) : PSWIZB_BACK);
}
else if(LOWORD(wParam) == IDC_BROWSE && HIWORD(wParam) == BN_CLICKED)
{
char cBuff[256], cBuff2[256];
GetDefaultTargetPath(pData->hInf, cBuff, cBuff2);
if(QueryTargetPath(hwnd,cBuff,cBuff2))
SetDlgItemText(hwnd, IDC_TARGETDIR, cBuff);
}
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func WizPage4Proc
* Funktion: WizPage4Proc
* Aufgabe.: fensterprozedur wizard-seite, die die installation durchfuehrt
* Resultat: abhaengig von der zu bearbeitenden message
* Hinweis.:
* ------------------------------------------------------------------------ */
LRESULT CALLBACK WizPage4Proc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam) /* zweiter message-parameter */
{
tWizardData* pData = (tWizardData*)GetWindowLong(hwnd, DWL_USER);
switch(message)
{
case WM_INITDIALOG:
pData = (tWizardData*)((PROPSHEETPAGE*)lParam)->lParam;
SendDlgItemMessage(hwnd, IDC_HDR_TITLE,
WM_SETFONT, (WPARAM)pData->hHeaderTitleFont, 0);
SendDlgItemMessage(hwnd, IDC_STATIC,
STM_SETICON, (WPARAM)pData->hSmAlertIcon, 0);
SetDlgItemText(hwnd, IDC_HDR_TITLE, pData->cPage4HdrTitle);
SetDlgItemText(hwnd, IDC_HDR_SUBTITLE, pData->cPage4HdrSubTitle);
SetWindowLong(hwnd, DWL_USER, (LONG)pData);
SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETSTEP, (WPARAM)1, 0);
return 1;
case WM_NOTIFY:
if(((NMHDR*)lParam)->code == PSN_SETACTIVE)
{
int iNeedWinCD;
iNeedWinCD = CheckProductsForFlag(pData->hInf, ProductList, 0x04);
ShowWindow(GetDlgItem(hwnd,IDC_TEXT1), /* show 'you need your */
iNeedWinCD ? SW_SHOW : SW_HIDE); /* windows cd' message */
ShowWindow(GetDlgItem(hwnd,IDC_STATIC),
iNeedWinCD ? SW_SHOW : SW_HIDE);
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_BACK|PSWIZB_NEXT);
if(DisableUI) PropSheet_PressButton(GetParent(hwnd), PSBTN_NEXT);
}
else if(((NMHDR*)lParam)->code == PSN_QUERYCANCEL) /* user canceled? */
{
if(GetWindowLong(hwnd,GWL_USERDATA)) /* install thread running? */
SetWindowLong(hwnd, DWL_MSGRESULT, 1); /* -> ignore cancel */
}
else if(((NMHDR*)lParam)->code == PSN_WIZNEXT) /* user clicked next? */
{
int iDummy;
PropSheet_SetWizButtons(GetParent(hwnd), 0); /* disable */
EnableWindow(GetDlgItem(GetParent(hwnd),IDCANCEL), 0); /* buttons */
SetWindowLong(hwnd, DWL_MSGRESULT, 1); /* stay on this page */
SetWindowLong(hwnd, GWL_USERDATA, 1); /* flag: thread is running */
CreateThread(0, 0, InstallThread, (void*)hwnd, 0, &iDummy);
}
return 1;
case WM_USER_STEP:
{
int iNewString;
char cText[256];
HINSTANCE hInstance;
hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
switch((int)wParam)
{
case 2: iNewString = STR_STOPSERVICE; break;
case 3: iNewString = STR_COPYING; break;
case 4: iNewString = STR_REGISTRY; break;
case 5: iNewString = STR_SHORTCUTS; break;
case 6: iNewString = STR_STARTSERVICE; break;
default: iNewString = 0; break;
}
if(iNewString)
{
LoadString(hInstance, iNewString, cText, sizeof(cText));
SetDlgItemText(hwnd, IDC_TEXT2, cText);
ShowWindow(GetDlgItem(hwnd,IDC_PROGRESS), SW_SHOW);
}
else
{
SetDlgItemText(hwnd, IDC_TEXT2, "");
ShowWindow(GetDlgItem(hwnd,IDC_PROGRESS), SW_HIDE);
}
return 1;
}
case WM_USER_PROGRESS:
if(wParam) /* advance one step */
{
SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_STEPIT, 0, 0);
}
else /* init progress step count */
{
SendDlgItemMessage(hwnd,
IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0,lParam));
}
return 1;
case WM_USER_RESULT: /* thread has finished his work */
{
char cText[512];
HINSTANCE hInstance;
hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
SetWindowLong(hwnd, GWL_USERDATA, 0); /* set flag: thread not running */
if(!wParam) /* install not succesfull? */
{
LoadString(hInstance, STR_INSTALLFAIL, cText, sizeof(cText));
ErrorMessageBox(hwnd, cText, (int)lParam);
SetDlgItemText(hwnd, IDC_TEXT2, "");
SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);
PropSheet_SetWizButtons(GetParent(hwnd),PSWIZB_BACK|PSWIZB_NEXT);
EnableWindow(GetDlgItem(GetParent(hwnd),IDCANCEL), 1);
}
else /* install succesfull? */
{
PropSheet_SetCurSel(GetParent(hwnd), 0, 4);
}
return 1;
}
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func WizPage5Proc
* Funktion: WizPage5Proc
* Aufgabe.: fensterprozedur installation-complete-page
* Resultat: abhaengig von der zu bearbeitenden message
* Hinweis.:
* ------------------------------------------------------------------------ */
LRESULT CALLBACK WizPage5Proc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam) /* zweiter message-parameter */
{
tWizardData* pData = (tWizardData*)GetWindowLong(hwnd, DWL_USER);
switch(message)
{
case WM_INITDIALOG:
pData = (tWizardData*)((PROPSHEETPAGE*)lParam)->lParam;
SendDlgItemMessage(hwnd, IDC_TEXT1, WM_SETFONT,
(WPARAM)pData->hWelcomeTitleFont, 0);
SendDlgItemMessage(hwnd, IDC_STATIC,
STM_SETICON, (WPARAM)pData->hSmAlertIcon, 0);
return 1;
case WM_NOTIFY:
if(((NMHDR*)lParam)->code == PSN_SETACTIVE)
{
ShowWindow(GetDlgItem(hwnd,IDC_TEXT2), Reboot ? SW_SHOW : SW_HIDE);
ShowWindow(GetDlgItem(hwnd,IDC_STATIC), Reboot ? SW_SHOW : SW_HIDE);
EnableWindow(GetDlgItem(GetParent(hwnd),IDCANCEL), 0);
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH);
if(DisableUI) PropSheet_PressButton(GetParent(hwnd), PSBTN_FINISH);
}
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func WizPage6Proc
* Funktion: WizPage6Proc
* Aufgabe.: fensterprozedur der uninstall-page des wizard-property-sheets
* Resultat: abhaengig von der zu bearbeitenden message
* ------------------------------------------------------------------------ */
LRESULT CALLBACK WizPage6Proc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam) /* zweiter message-parameter */
{
tWizardData* pData = (tWizardData*)GetWindowLong(hwnd, DWL_USER);
switch(message)
{
case WM_INITDIALOG:
{
HICON hIcon;
int iIconIdx;
char cProdName[256];
pData = (tWizardData*)((PROPSHEETPAGE*)lParam)->lParam;
SetWindowLong(hwnd, DWL_USER, (LONG)pData);
GetUninstallProductName(pData->hInf,
ProductList, cProdName, sizeof(cProdName), &iIconIdx);
SendDlgItemMessage(hwnd, IDC_TEXT1, WM_SETFONT,
(WPARAM)pData->hWelcomeTitleFont, 0);
SendDlgItemMessage(hwnd, IDC_TEXT2, WM_SETFONT,
(WPARAM)pData->hHeaderTitleFont, 0);
SetDlgItemText(hwnd, IDC_TEXT1, pData->cWelcomeTitle);
SetDlgItemText(hwnd, IDC_TEXT2, cProdName);
if(iIconIdx)
{
hIcon = ImageList_GetIcon(pData->hImgLst, iIconIdx+1, ILD_NORMAL);
SendDlgItemMessage(hwnd, IDC_STATIC, STM_SETICON, (WPARAM)hIcon, 0);
}
// SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETSTEP, (WPARAM)1, 0);
CenterWindow(GetParent(hwnd), GetDesktopWindow());
return 1;
}
case WM_NOTIFY:
if(((NMHDR*)lParam)->code == PSN_SETACTIVE)
{
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT);
if(DisableUI) PropSheet_PressButton(GetParent(hwnd), PSBTN_NEXT);
}
else if(((NMHDR*)lParam)->code == PSN_QUERYCANCEL) /* user canceled? */
{
if(GetWindowLong(hwnd,GWL_USERDATA)) /* install thread running? */
SetWindowLong(hwnd, DWL_MSGRESULT, 1); /* -> ignore cancel */
}
else if(((NMHDR*)lParam)->code == PSN_WIZNEXT) /* user clicked next? */
{
int iDummy;
PropSheet_SetWizButtons(GetParent(hwnd), 0); /* disable */
EnableWindow(GetDlgItem(GetParent(hwnd),IDCANCEL), 0); /* buttons */
SetWindowLong(hwnd, DWL_MSGRESULT, 1); /* stay on this page */
SetWindowLong(hwnd, GWL_USERDATA, 1); /* flag: thread is running */
CreateThread(0, 0, RemoveThread, (void*)hwnd, 0, &iDummy);
}
return 1;
case WM_USER_STEP:
{
int iNewString;
char cText[256];
HINSTANCE hInstance;
hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
switch((int)wParam)
{
case 2: iNewString = STR_STOPSERVICE; break;
case 3: iNewString = STR_DELETING; break;
case 4: iNewString = STR_REGISTRY; break;
case 5: iNewString = STR_SHORTCUTS; break;
case 6: iNewString = STR_STARTSERVICE; break;
default: iNewString = 0; break;
}
if(iNewString)
{
LoadString(hInstance, iNewString, cText, sizeof(cText));
SetDlgItemText(hwnd, IDC_TEXT3, cText);
// ShowWindow(GetDlgItem(hwnd,IDC_PROGRESS), SW_SHOW);
}
else
{
SetDlgItemText(hwnd, IDC_TEXT3, "");
// ShowWindow(GetDlgItem(hwnd,IDC_PROGRESS), SW_HIDE);
}
return 1;
}
// case WM_USER_PROGRESS:
//
// if(wParam) /* advance one step */
// {
// SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_STEPIT, 0, 0);
// }
// else /* init progress step count */
// {
// SendDlgItemMessage(hwnd,
// IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0,lParam));
// }
// return 1;
case WM_USER_RESULT: /* thread has finished his work */
{
char cText[512];
HINSTANCE hInstance;
hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
SetWindowLong(hwnd, GWL_USERDATA, 0); /* set flag: thread not running */
if(!wParam) /* uninstall not succesfull? */
{
LoadString(hInstance, STR_REMOVEFAIL, cText, sizeof(cText));
ErrorMessageBox(hwnd, cText, (int)lParam);
SetDlgItemText(hwnd, IDC_TEXT3, "");
// SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);
PropSheet_SetWizButtons(GetParent(hwnd),PSWIZB_BACK|PSWIZB_NEXT);
EnableWindow(GetDlgItem(GetParent(hwnd),IDCANCEL), 1);
}
else /* uninstall succesfull? */
{
PropSheet_SetCurSel(GetParent(hwnd), 0, 6);
}
return 1;
}
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func WizPage7Proc
* Funktion: WizPage7Proc
* Aufgabe.: fensterprozedur uninstall-complete-page
* Resultat: abhaengig von der zu bearbeitenden message
* ------------------------------------------------------------------------ */
LRESULT CALLBACK WizPage7Proc(HWND hwnd, /* fensterhandle */
UINT message, /* message */
WPARAM wParam, /* erster message-parameter */
LPARAM lParam) /* zweiter message-parameter */
{
tWizardData* pData = (tWizardData*)GetWindowLong(hwnd, DWL_USER);
switch(message)
{
case WM_INITDIALOG:
pData = (tWizardData*)((PROPSHEETPAGE*)lParam)->lParam;
SendDlgItemMessage(hwnd, IDC_TEXT1, WM_SETFONT,
(WPARAM)pData->hWelcomeTitleFont, 0);
SendDlgItemMessage(hwnd, IDC_STATIC,
STM_SETICON, (WPARAM)pData->hSmAlertIcon, 0);
return 1;
case WM_NOTIFY:
if(((NMHDR*)lParam)->code == PSN_SETACTIVE)
{
ShowWindow(GetDlgItem(hwnd,IDC_TEXT2), Reboot ? SW_SHOW : SW_HIDE);
ShowWindow(GetDlgItem(hwnd,IDC_STATIC), Reboot ? SW_SHOW : SW_HIDE);
EnableWindow(GetDlgItem(GetParent(hwnd),IDCANCEL), 0);
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH);
if(DisableUI) PropSheet_PressButton(GetParent(hwnd), PSBTN_FINISH);
}
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func InstallThread
* Funktion: InstallThread
* Aufgabe.: fuehrt die installation durch
* Resultat: wird nicht ausgewertet
* ------------------------------------------------------------------------ */
DWORD WINAPI InstallThread(void* pArg) /* thread-parameter */
{
HWND hwnd;
tWizardData* pData;
int iSuccess, iErrCode = 0;
if(IS_WINNT) SetThreadLocale(MAKELCID(AppLang,SORT_DEFAULT));
hwnd = (HWND)pArg;
pData = (tWizardData*)GetWindowLong(hwnd, DWL_USER);
CatchReboot = 1;
BuildInstallSectionList(pData->hInf, ProductList, SectionList);
CreateUninstallEntrys(pData->hInf, ProductList);
iSuccess = InstallMultipleSections(pData->hInf, SectionList, hwnd);
if(!iSuccess) iErrCode = GetLastError();
else if(CheckProductsForFlag(pData->hInf,ProductList,0x02)) Reboot = 1;
CatchReboot = 0;
PostMessage(hwnd, WM_USER_RESULT, (WPARAM)iSuccess, (LPARAM)iErrCode);
return 0;
}
/* ------------------------------------------------------------------------
* $Func RemoveThread
* Funktion: RemoveThread
* Aufgabe.: fuehrt die de-installation durch
* Resultat: wird nicht ausgewertet
* ------------------------------------------------------------------------ */
DWORD WINAPI RemoveThread(void* pArg) /* thread-parameter */
{
HWND hwnd;
char Path[256];
tWizardData* pData;
int iSuccess, iErrCode = 0;
if(IS_WINNT) SetThreadLocale(MAKELCID(AppLang,SORT_DEFAULT));
hwnd = (HWND)pArg;
pData = (tWizardData*)GetWindowLong(hwnd, DWL_USER);
CatchReboot = 1;
if(GetLastUserDir(pData->hInf,ProductList,Path))
SetupSetDirectoryId(pData->hInf,DIRID_USER,Path);
BuildRemoveSectionList(pData->hInf, ProductList, SectionList);
RemoveUninstallEntrys(pData->hInf, ProductList);
iSuccess = InstallMultipleSections(pData->hInf, SectionList, hwnd);
if(!iSuccess) iErrCode = GetLastError();
else if(CheckProductsForFlag(pData->hInf,ProductList,0x02)) Reboot = 1;
CatchReboot = 0;
PostMessage(hwnd, WM_USER_RESULT, (WPARAM)iSuccess, (LPARAM)iErrCode);
return 0;
}
/* ------------------------------------------------------------------------
* $Func InitPlatformSectionNames
* Funktion: InitPlatformSectionNames
* Aufgabe.: initialisiert den dialog mit der produkt-auswahl
* Resultat: keins
* Hinweis.:
* ------------------------------------------------------------------------ */
void InitPlatformSectionNames(HINF hInf) /* handle der inf-datei */
{
INFCONTEXT infContext;
if(IS_WINNT)
{
if(IS_WIN2K && SetupFindFirstLine(hInf,"Install.NT5",0,&infContext))
InstallSect = "Install.NT5";
else if(SetupFindFirstLine(hInf,"Install.NTx86",0,&infContext))
InstallSect = "Install.NTx86";
else if(SetupFindFirstLine(hInf,"Install.NT",0,&infContext))
InstallSect = "Install.NT";
else
InstallSect = "Install";
if(IS_WIN2K && SetupFindFirstLine(hInf,"Remove.NT5",0,&infContext))
RemoveSect = "Remove.NT5";
else if(SetupFindFirstLine(hInf,"Remove.NTx86",0,&infContext))
RemoveSect = "Remove.NTx86";
else if(SetupFindFirstLine(hInf,"Remove.NT",0,&infContext))
RemoveSect = "Remove.NT";
else
RemoveSect = "Remove";
if(IS_WIN2K && SetupFindFirstLine(hInf,"Products.NT5",0,&infContext))
ProductSect = "Products.NT5";
else if(SetupFindFirstLine(hInf,"Products.NTx86",0,&infContext))
ProductSect = "Products.NTx86";
else if(SetupFindFirstLine(hInf,"Products.NT",0,&infContext))
ProductSect = "Products.NT";
else
ProductSect = "Products";
}
else
{
if(SetupFindFirstLine(hInf,"Install.Win",0,&infContext))
InstallSect = "Install.Win";
else
InstallSect = "Install";
if(SetupFindFirstLine(hInf,"Remove.Win",0,&infContext))
RemoveSect = "Remove.Win";
else
RemoveSect = "Remove";
if(SetupFindFirstLine(hInf,"Products.Win",0,&infContext))
ProductSect = "Products.Win";
else
ProductSect = "Products";
}
}
/* ------------------------------------------------------------------------
* $Func InitProductSelection
* Funktion: InitProductSelection
* Aufgabe.: initialisiert den dialog mit der produkt-auswahl
* Resultat: anzahl der produkte, die installiert werden koennen
* ------------------------------------------------------------------------ */
int InitProductSelection(HWND hwnd, /* handle des dialogs */
HINF hInf /* handle der inf-datei */
)
{
char Buff[256];
INFCONTEXT infContext;
int Cnt = 0, Sel, Pic, Idx, Old;
if(SetupFindFirstLine(hInf,ProductSect,0,&infContext))
do
{
if(!SetupGetStringField(&infContext,2,Buff,sizeof(Buff),0) ||
!strlen(Buff)) continue;
if(!SetupGetStringField(&infContext,1,Buff,sizeof(Buff),0))
continue;
Idx = (int)SendDlgItemMessage(hwnd,
IDC_PRODLIST, LB_ADDSTRING, 0, (LPARAM)Buff);
Old = (GetProductVersionDiff(hInf,Idx) < 0);
Sel = SetupGetStringField(&infContext,4,Buff,sizeof(Buff),0) ?
((atoi(Buff) & 0x01) && !Old) : 0;
Pic = SetupGetStringField(&infContext,5,Buff,sizeof(Buff),0) ?
atoi(Buff) : 0;
SelectLBSetImage(GetDlgItem(hwnd,IDC_PRODLIST), Idx, Pic, Old);
SelectLBCheckItem(GetDlgItem(hwnd,IDC_PRODLIST), Idx, Sel);
Cnt++;
}
while(SetupFindNextLine(&infContext, &infContext));
return Cnt;
}
/* ------------------------------------------------------------------------
* $Func BuildProductList
* Funktion: BuildProductList
* Aufgabe.: baut eine liste der selektierten produkte auf
* Resultat: anzahl der produkte, die selektiert sind
* ------------------------------------------------------------------------ */
int BuildProductList(HWND hwnd, /* handle des dialogs */
HINF hInf, /* handle der inf-datei */
char* ProdList /* puffer fuer liste */
)
{
char Buff[256];
INFCONTEXT infContext;
int Cnt = 0, Idx = 0;
ProdList[0] = ProdList[1] = 0;
if(SetupFindFirstLine(hInf,ProductSect,0,&infContext))
do
{
if(!SetupGetStringField(&infContext,2,Buff,sizeof(Buff),0) ||
!strlen(Buff)) continue;
if(!SelectLBIsItemChecked(GetDlgItem(hwnd,IDC_PRODLIST),Idx++))
continue;
if(!SetupGetStringField(&infContext,0,ProdList,128,0))
continue;
ProdList += strlen(ProdList)+1;
Cnt++;
}
while(SetupFindNextLine(&infContext,&infContext));
ProdList[0] = 0;
return Cnt;
}
/* ------------------------------------------------------------------------
* $Func BuildInstallSectionList
* Funktion: BuildInstallSectionList
* Aufgabe.: baut eine liste von sektionen die installiert werden sollen
* Resultat: anzahl sektionen
* ------------------------------------------------------------------------ */
int BuildInstallSectionList(HINF hInf, /* handle der inf-datei */
char* ProdList, /* liste selektierter produkte */
char* SectList /* puffer fuer section-liste */
)
{
int Cnt = 1;
INFCONTEXT infContext;
strcpy(SectList, InstallSect);
SectList += strlen(SectList)+1;
while(*ProdList)
{
if(SetupFindFirstLine(hInf,ProductSect,ProdList,&infContext) &&
SetupGetStringField(&infContext,2,SectList,128,0))
SectList += strlen(SectList)+1, Cnt++;
ProdList += strlen(ProdList)+1;
}
SectList[0] = 0;
return Cnt;
}
/* ------------------------------------------------------------------------
* $Func BuildRemoveSectionList
* Funktion: BuildRemoveSectionList
* Aufgabe.: baut eine liste von sektionen die deinstalliert werden sollen
* Resultat: anzahl sektionen
* Hinweis.:
* ------------------------------------------------------------------------ */
int BuildRemoveSectionList(HINF hInf, /* handle der inf-datei */
char* ProdList, /* liste selektierter produkte */
char* SectList /* puffer fuer section-liste */
)
{
HKEY hKey;
int Rest = 0, Cnt = 1;
INFCONTEXT infContext;
char* pProd, Prod[256], Key[256];
if(SetupFindFirstLine(hInf,ProductSect,0,&infContext))
do
{
if(!SetupGetStringField(&infContext,0,Prod,sizeof(Prod),0)) continue;
sprintf(Key, REG_UNINSTALL_PATH "\\%s", Prod);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,Key,0,KEY_ALL_ACCESS,
&hKey) != ERROR_SUCCESS) continue;
RegCloseKey(hKey);
Rest++;
pProd = ProdList;
while(*pProd)
{
if(!stricmp(pProd,Prod)) Rest--;
pProd += strlen(pProd)+1;
}
}
while(SetupFindNextLine(&infContext, &infContext));
while(*ProdList)
{
if(SetupFindFirstLine(hInf,ProductSect,ProdList,&infContext) &&
SetupGetStringField(&infContext,3,SectList,128,0))
SectList += strlen(SectList)+1, Cnt++;
ProdList += strlen(ProdList)+1;
}
if(!Rest) strcpy(SectList, RemoveSect), SectList += strlen(SectList)+1;
SectList[0] = 0;
return Cnt;
}
/* ------------------------------------------------------------------------
* $Func CheckProductsForFlag
* Funktion: CheckProductsForFlag
* Aufgabe.: ueberprueft ob bei einem der produkte ein flag gesetzt ist
* Resultat: anzahl produkte, bei denen das flag gesetzt ist
* Hinweis.:
* ------------------------------------------------------------------------ */
int CheckProductsForFlag(HINF hInf, /* handle der inf-datei */
char* ProdList, /* liste selektierter produkte */
int iFlag) /* zu pruefendes flag */
{
int Cnt;
char Buff[256];
INFCONTEXT infContext;
for(Cnt = 0; *ProdList; ProdList += strlen(ProdList)+1)
{
if(!SetupFindFirstLine(hInf,ProductSect,ProdList,&infContext))
continue;
if(!SetupGetStringField(&infContext,4,Buff,sizeof(Buff),0))
continue;
if(atoi(Buff) & iFlag) Cnt++;
}
return Cnt;
}
/* ------------------------------------------------------------------------
* $Func GetProductDescription
* Funktion: GetProductDescription
* Aufgabe.: liefert die beschreibung eines produktes
* Resultat: keins
* Hinweis.:
* ------------------------------------------------------------------------ */
void GetProductDescription(HINF hInf, /* handle der inf-datei */
int ProdIdx, /* index des produkts */
char* Buff, /* ^puffer */
int szBuff) /* groesse des puffers */
{
char cTmp[128];
INFCONTEXT infContext;
Buff[0] = 0;
if(!SetupFindFirstLine(hInf,ProductSect,0,&infContext))
return;
do
{
if(!SetupGetStringField(&infContext,2,cTmp,sizeof(cTmp),0) ||
!strlen(cTmp)) continue;
SetupGetStringField(&infContext, 6, Buff, szBuff, 0);
if(!ProdIdx--) return;
}
while(SetupFindNextLine(&infContext,&infContext));
return;
}
/* ------------------------------------------------------------------------
* $Func GetProductVersionDiff
* Funktion: GetProductVersionDiff
* Aufgabe.: liefert die versions-differenz eines installierten produktes
* Resultat: > 0 wenn wenn die vorhandene version aelter ist als die zu
* installierende, < 0 wenn die vorhandene version neuer ist.
* Hinweis.:
* ------------------------------------------------------------------------ */
int GetProductVersionDiff(HINF hInf, /* handle der inf-datei */
int ProdIdx) /* index des produkts */
{
HKEY hKey;
LONG iType;
INFCONTEXT infContext;
int iSize, iResult, iVerOld, iVerNew;
char * pOld, * pNew, cTmp[128], cVer[128], cKey[MAX_PATH];
if(!SetupFindFirstLine(hInf,ProductSect,0,&infContext))
return 0;
do
{
if(!SetupGetStringField(&infContext,2,cTmp,sizeof(cTmp),0) ||
!strlen(cTmp)) continue; /* hat keine install-section */
if(ProdIdx--)
continue; /* index noch nicht erreicht */
if(!SetupGetStringField(&infContext,0,cTmp,sizeof(cTmp),0))
return 0; /* produkt-name nicht vorhanden */
if(!SetupGetStringField(&infContext,7,cVer,sizeof(cVer),0))
return 0; /* neue version nicht vorhanden */
sprintf(cKey, REG_UNINSTALL_PATH "\\%s", cTmp);
iResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, cKey, 0, KEY_READ, &hKey);
if(iResult != ERROR_SUCCESS) return 0; /* alte version unbekannt */
iSize = sizeof(cTmp);
iResult = RegQueryValueEx(hKey, "ProductVersion", 0, &iType, cTmp, &iSize);
RegCloseKey(hKey);
if(iResult != ERROR_SUCCESS) return 0; /* alte version unbekannt */
for(pOld = cTmp, pNew = cVer; ; )
{
iVerOld = strtol(pOld, &pOld, 10);
iVerNew = strtol(pNew, &pNew, 10);
if(iVerOld != iVerNew) break;
if(*pOld++ != '.') break;
if(*pNew++ != '.') break;
}
return iVerNew - iVerOld; /* versions-differenz berechnen */
}
while(SetupFindNextLine(&infContext,&infContext));
return 0;
}
/* ------------------------------------------------------------------------
* $Func CreateUninstallEntrys
* Funktion: CreateUninstallEntrys
* Aufgabe.: legt uninstall-eintraege in der registry an
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int CreateUninstallEntrys(HINF hInf, /* handle der inf-datei */
char* ProdList /* liste selektierter produkte */
)
{
HKEY hKey;
LONG Type;
INFCONTEXT infContext;
char Key[256], Cmd[MAX_PATH], Name[256], Sect[256], Uninst[256], Ver[256];
while(*ProdList)
{
if(SetupFindFirstLine(hInf,ProductSect,ProdList,&infContext) &&
SetupGetStringField(&infContext,1,Name,sizeof(Name),0) &&
SetupGetStringField(&infContext,2,Sect,sizeof(Sect),0) &&
SetupGetStringField(&infContext,3,Uninst,sizeof(Uninst),0) &&
strlen(Uninst))
{
if(!QuerySetupExePath(hInf,Sect,Cmd) &&
!QuerySetupExePath(hInf,InstallSect,Cmd)) return 0;
strcat(Cmd, " /remove:");
strcat(Cmd, ProdList);
sprintf(Key, REG_UNINSTALL_PATH "\\%s", ProdList);
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,Key,0,0,0,KEY_ALL_ACCESS,0,
&hKey,&Type) != ERROR_SUCCESS) return 0;
RegSetValueEx(hKey, "DisplayName", 0, REG_SZ, Name, strlen(Name)+1);
RegSetValueEx(hKey, "UninstallString", 0, REG_SZ, Cmd, strlen(Cmd)+1);
if(SetupGetStringField(&infContext,7,Ver,sizeof(Ver),0))
RegSetValueEx(hKey, "ProductVersion", 0, REG_SZ, Ver, strlen(Ver)+1);
if(strlen(UserTargetDir))
RegSetValueEx(hKey, "UserTargetDir",
0, REG_SZ, UserTargetDir, strlen(UserTargetDir)+1);
RegCloseKey(hKey);
}
ProdList += strlen(ProdList)+1;
}
if(SetupFindFirstLine(hInf,InstallSect,"Uninstall",&infContext) &&
SetupGetStringField(&infContext,1,Sect,sizeof(Sect),0))
{
if(!SetupGetStringField(&infContext,2,Name,sizeof(Name),0))
strcpy(Name, Sect);
if(!QuerySetupExePath(hInf,InstallSect,Cmd)) return 0;
strcat(Cmd, " /remove:");
strcat(Cmd, Sect);
sprintf(Key, REG_UNINSTALL_PATH "\\%s", Sect);
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,Key,0,0,0,KEY_ALL_ACCESS,0,
&hKey,&Type) != ERROR_SUCCESS) return 0;
RegSetValueEx(hKey, "DisplayName", 0, REG_SZ, Name, strlen(Name)+1);
RegSetValueEx(hKey, "UninstallString", 0, REG_SZ, Cmd, strlen(Cmd)+1);
if(strlen(UserTargetDir))
RegSetValueEx(hKey, "UserTargetDir", 0,
REG_SZ, UserTargetDir, strlen(UserTargetDir)+1);
RegCloseKey(hKey);
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func GetUninstallProductName
* Funktion: GetUninstallProductName
* Aufgabe.: liefert den namen des produkts, das deinstalliert wird
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int GetUninstallProductName(HINF hInf, /* handle der inf-datei */
char* ProdList, /* uninstall-produkt */
char* Name, /* puffer fuer name */
int cbName, /* groesse des puffers */
int* iIconIdx) /* index des product-icons */
{
INFCONTEXT infContext;
char cIcon[64], cKey[256];
if(strlen(ProdList) &&
SetupFindFirstLine(hInf,ProductSect,ProdList,&infContext) &&
SetupGetStringField(&infContext,1,Name,cbName,0))
{
if(SetupGetStringField(&infContext,5,cIcon,sizeof(cIcon),0))
*iIconIdx = atoi(cIcon);
else *iIconIdx = 0;
return 1;
}
if(SetupFindFirstLine(hInf,InstallSect,"Uninstall",&infContext) &&
SetupGetStringField(&infContext,1,cKey,sizeof(cKey),0) &&
(!strlen(ProdList) || !stricmp(cKey,ProdList)) &&
SetupGetStringField(&infContext,2,Name,cbName,0))
{
*iIconIdx = 0;
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func GetLastUserDir
* Funktion: GetLastUserDir
* Aufgabe.: liefert das verzeichnis, in das zuletzt installiert wurde
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int GetLastUserDir(HINF hInf, /* handle der inf-datei */
char* ProdList, /* liste von produkten */
char* Path /* puffer fuer pfad */
)
{
HKEY hKey;
LONG Type;
int rc, Size;
INFCONTEXT infCont;
char Key[256], Prod[256];
while(ProdList && *ProdList)
{
sprintf(Key, REG_UNINSTALL_PATH "\\%s", ProdList);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,Key,0,KEY_READ,&hKey) == ERROR_SUCCESS)
{
Size = MAX_PATH;
rc = RegQueryValueEx(hKey, "UserTargetDir", 0, &Type, Path, &Size);
RegCloseKey(hKey);
if(rc == ERROR_SUCCESS) return 1;
}
ProdList += strlen(ProdList)+1;
}
if(SetupFindFirstLine(hInf,ProductSect,0,&infCont))
do
{
if(!SetupGetStringField(&infCont,0,Prod,sizeof(Prod),0)) continue;
sprintf(Key, REG_UNINSTALL_PATH "\\%s", Prod);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,Key,0,KEY_READ,&hKey) == ERROR_SUCCESS)
{
Size = MAX_PATH;
rc = RegQueryValueEx(hKey, "UserTargetDir", 0, &Type, Path, &Size);
RegCloseKey(hKey);
if(rc == ERROR_SUCCESS) return 1;
}
}
while(SetupFindNextLine(&infCont,&infCont));
if(SetupFindFirstLine(hInf,InstallSect,"Uninstall",&infCont) &&
SetupGetStringField(&infCont,1,Prod,sizeof(Prod),0))
{
sprintf(Key, REG_UNINSTALL_PATH "\\%s", Prod);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,Key,0,KEY_READ,&hKey) == ERROR_SUCCESS)
{
Size = MAX_PATH;
rc = RegQueryValueEx(hKey, "UserTargetDir", 0, &Type, Path, &Size);
RegCloseKey(hKey);
if(rc == ERROR_SUCCESS) return 1;
}
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func RemoveUninstallEntrys
* Funktion: RemoveUninstallEntrys
* Aufgabe.: entfernt uninstall-eintraege aus der registry
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int RemoveUninstallEntrys(HINF hInf, /* handle der inf-datei */
char* ProdList /* liste selektierter produkte */
)
{
HKEY hKey;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_UNINSTALL_PATH,
0, KEY_READ, &hKey) != ERROR_SUCCESS) return 0;
while(*ProdList)
{
RegDeleteKey(hKey, ProdList);
ProdList += strlen(ProdList)+1;
}
RegCloseKey(hKey);
return 1;
}
/* ------------------------------------------------------------------------
* $Func InstallMultipleSections
* Funktion: InstallMultipleSections
* Aufgabe.: bearbeitet install-sections aus einer inf-datei
* Resultat: TRUE wenn erfolgreich, sonst GetLastError()
* Hinweis.:
* ------------------------------------------------------------------------ */
int InstallMultipleSections(HINF hInf, /* handle der inf-datei */
char* Sections, /* namen der install-sections */
HWND hwnd /* callback-fenster */
)
{
char* Section;
void** pContext;
HSPFILEQ FileQ;
FileQ = SetupOpenFileQueue();
Section = Sections;
while(*Section)
{
if(!SetupInstallFilesFromInfSection(hInf,0,FileQ,Section,".",SP_COPY_NEWER))
{
int err = GetLastError();
SetupCloseFileQueue(FileQ);
SetLastError(err);
return 0;
}
Section += strlen(Section)+1;
}
Section = Sections;
while(*Section)
{
if(!DoExecStatements(hInf,Section,1,hwnd)) return 0;
Section += strlen(Section)+1;
}
PostMessage(hwnd, WM_USER_STEP, (WPARAM)2, 0);
Section = Sections;
while(*Section)
{
if(!StopServices(hInf,Section)) Reboot = 1;
Section += strlen(Section)+1;
}
PostMessage(hwnd, WM_USER_STEP, (WPARAM)3, 0);
pContext = (void**)malloc(3*sizeof(void*));
pContext[0] = SetupInitDefaultQueueCallbackEx(hwnd,
hwnd, WM_USER_PROGRESS, 0, 0);
if(!SetupCommitFileQueue(hwnd,FileQ,QueueCallback,pContext))
{
int err = GetLastError();
SetupTermDefaultQueueCallback(pContext[0]);
free(pContext);
SetupCloseFileQueue(FileQ);
SetLastError(err);
return 0;
}
SetupTermDefaultQueueCallback(pContext[0]);
free(pContext);
if(SetupPromptReboot(FileQ,hwnd,1) & SPFILEQ_FILE_IN_USE) Reboot = 1;
SetupCloseFileQueue(FileQ);
PostMessage(hwnd, WM_USER_STEP, (WPARAM)4, 0);
Section = Sections;
while(*Section)
{
if(!SetupInstallFromInfSection(hwnd,hInf,Section,SPINST_INIFILES|
SPINST_REGISTRY|SPINST_INI2REG,0,0,0,0,0,0,0)) return 0;
Section += strlen(Section)+1;
}
Section = Sections;
while(*Section)
{
if(!InstallServices(hInf,Section)) return 0;
Section += strlen(Section)+1;
}
PostMessage(hwnd, WM_USER_STEP, (WPARAM)5, 0);
Section = Sections;
while(*Section)
{
if(!UpdateShortcuts(hInf,Section)) return 0;
Section += strlen(Section)+1;
}
PostMessage(hwnd, WM_USER_STEP, (WPARAM)6, 0);
Section = Sections;
while(*Section)
{
if(!StartServices(hInf,Section)) Reboot = 1;
Section += strlen(Section)+1;
}
PostMessage(hwnd, WM_USER_STEP, (WPARAM)-1, 0);
Section = Sections;
while(*Section)
{
if(!DoExecStatements(hInf,Section,2,hwnd)) return 0;
Section += strlen(Section)+1;
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func StopServices
* Funktion: InstallServices
* Aufgabe.: stopt services aus einer service-install-section
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int StopServices(HINF hInf, /* handle der inf-datei */
char* Section /* name der install-section */
)
{
INFCONTEXT infCont;
char SvcSect[256], Cmd[256], Name[256];
if(!IS_WINNT) return 1;
sprintf(SvcSect, "%s.Services", Section);
if(SetupFindFirstLine(hInf,SvcSect,0,&infCont))
{
do
{
if(!SetupGetStringField(&infCont,0,Cmd,sizeof(Cmd),0)) continue;
if(!SetupGetStringField(&infCont,1,Name,sizeof(Name),0)) continue;
if(stricmp(Cmd,"StopService")) continue;
if(!DoStopService(Name)) return 0;
}
while(SetupFindNextLine(&infCont,&infCont));
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func StartServices
* Funktion: StartServices
* Aufgabe.: startet services aus einer service-install-section
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int StartServices(HINF hInf, /* handle der inf-datei */
char* Section /* name der install-scetion */
)
{
INFCONTEXT infCont;
char SvcSect[256], Cmd[256], Name[256];
if(!IS_WINNT) return 1;
sprintf(SvcSect, "%s.Services", Section);
if(SetupFindFirstLine(hInf,SvcSect,0,&infCont))
{
do
{
if(!SetupGetStringField(&infCont,0,Cmd,sizeof(Cmd),0)) continue;
if(!SetupGetStringField(&infCont,1,Name,sizeof(Name),0)) continue;
if(stricmp(Cmd,"StartService")) continue;
if(!DoStartService(Name)) return 0;
}
while(SetupFindNextLine(&infCont,&infCont));
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func InstallServices
* Funktion: InstallServices
* Aufgabe.: bearbeitet service-install-section
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int InstallServices(HINF hInf, /* handle der inf-datei */
char* Section /* name der install-section */
)
{
INFCONTEXT infCont;
char SvcSect[256], Cmd[256], Name[256], InstSect[256];
if(!IS_WINNT) return 1;
sprintf(SvcSect, "%s.Services", Section);
if(SetupFindFirstLine(hInf,SvcSect,0,&infCont))
{
do
{
if(!SetupGetStringField(&infCont,0,Cmd,sizeof(Cmd),0)) continue;
if(!SetupGetStringField(&infCont,1,Name,sizeof(Name),0)) continue;
if(!stricmp(Cmd,"AddService"))
{
SetupGetStringField(&infCont,3,InstSect,sizeof(InstSect),0);
if(!DoAddService(hInf,Name,InstSect)) return 0;
}
else if(!stricmp(Cmd,"DelService"))
{
if(!DoDelService(Name)) return 0;
}
}
while(SetupFindNextLine(&infCont,&infCont));
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func DoStopService
* Funktion: DoStopService
* Aufgabe.: stopt einen service
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int DoStopService(char* SvcName) /* service-name */
{
int Cnt = 0;
SERVICE_STATUS svcStatus;
SC_HANDLE hManager, hService;
hManager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
if(!hManager) return 0;
hService = OpenService(hManager, SvcName, SERVICE_ALL_ACCESS);
if(!hService && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
{
CloseServiceHandle(hManager);
return 0;
}
else if(hService)
{
QueryServiceStatus(hService, &svcStatus);
if(svcStatus.dwCurrentState != SERVICE_STOPPED)
ControlService(hService, SERVICE_CONTROL_STOP, &svcStatus);
while(svcStatus.dwCurrentState != SERVICE_STOPPED && Cnt++ < 20)
Sleep(250), QueryServiceStatus(hService, &svcStatus);
CloseServiceHandle(hService);
if(svcStatus.dwCurrentState != SERVICE_STOPPED)
{
CloseServiceHandle(hManager);
return 0;
}
}
CloseServiceHandle(hManager);
return 1;
}
/* ------------------------------------------------------------------------
* $Func DoAddService
* Funktion: DoAddService
* Aufgabe.: fuegt einen service hinzu (wie in einer inf-section angegeben)
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int DoAddService(HINF hInf, /* handle der inf-datei */
char* SvcName, /* name des services */
char* SvcSection /* install-section des svc. */
)
{
INFCONTEXT infCont;
SC_HANDLE hManager, hService;
char SvcDesc[256], SvcBinary[256],
LoadOrdGrp[256], Depend[256], StartName[256];
char* pSvcDesc = 0, *pSvcBinary = 0,
*pLoadOrdGrp = 0, *pDepend = 0, *pStartName = 0;
int Idx = 1, SvcType = 0, StartType = 0, ErrorCtrl = 0;
if(!SetupFindFirstLine(hInf,SvcSection,0,&infCont)) return 0;
if(SetupFindFirstLine(hInf,SvcSection,"DisplayName",&infCont))
SetupGetStringField(&infCont,1,SvcDesc,sizeof(SvcDesc),0),
pSvcDesc = SvcDesc;
if(SetupFindFirstLine(hInf,SvcSection,"ServiceType",&infCont))
SetupGetIntField(&infCont,1,&SvcType);
if(SetupFindFirstLine(hInf,SvcSection,"StartType",&infCont))
SetupGetIntField(&infCont,1,&StartType);
if(SetupFindFirstLine(hInf,SvcSection,"ErrorControl",&infCont))
SetupGetIntField(&infCont,1,&ErrorCtrl);
if(SetupFindFirstLine(hInf,SvcSection,"ServiceBinary",&infCont))
SetupGetStringField(&infCont,1,SvcBinary,sizeof(SvcBinary),0),
pSvcBinary = SvcBinary;
if(SetupFindFirstLine(hInf,SvcSection,"LoadOrderGroup",&infCont))
SetupGetStringField(&infCont,1,LoadOrdGrp,sizeof(LoadOrdGrp),0),
pLoadOrdGrp = LoadOrdGrp;
if(SetupFindFirstLine(hInf,SvcSection,"Dependencies",&infCont))
{
pDepend = Depend;
while(SetupGetStringField(&infCont,Idx++,pDepend,sizeof(Depend),0))
pDepend += strlen(pDepend)+1;
pDepend[0] = 0;
pDepend = Depend;
}
if(SetupFindFirstLine(hInf,SvcSection,"StartName",&infCont))
SetupGetStringField(&infCont,1,StartName,sizeof(StartName),0),
pStartName = StartName;
hManager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
if(!hManager) return 0;
hService = OpenService(hManager, SvcName, SERVICE_ALL_ACCESS);
if(hService)
{
ChangeServiceConfig(hService, SvcType, StartType, ErrorCtrl,
pSvcBinary, pLoadOrdGrp, 0, pDepend, pStartName, 0, pSvcDesc);
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
AddServiceToGroupOrder(hInf,SvcSection);
return 1;
}
hService = CreateService(hManager, SvcName, pSvcDesc,
SERVICE_ALL_ACCESS, SvcType, StartType, ErrorCtrl, pSvcBinary,
pLoadOrdGrp, 0, pDepend, pStartName, 0);
if(hService)
{
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
AddServiceToGroupOrder(hInf,SvcSection);
return 1;
}
CloseServiceHandle(hManager);
return 0;
}
/* ------------------------------------------------------------------------
* $Func DoDelService
* Funktion: DoDelService
* Aufgabe.: loescht einen service
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int DoDelService(char* SvcName) /* name des services */
{
SC_HANDLE hManager, hService;
hManager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
if(!hManager) return 0;
hService = OpenService(hManager, SvcName, SERVICE_ALL_ACCESS);
if(!hService && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
{
CloseServiceHandle(hManager);
return 0;
}
else if(hService)
{
DeleteService(hService);
CloseServiceHandle(hService);
}
CloseServiceHandle(hManager);
return 1;
}
/* ------------------------------------------------------------------------
* $Func DoStartService
* Funktion: DoStartService
* Aufgabe.: startet einen service
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int DoStartService(char* SvcName) /* name des services */
{
int Cnt = 0;
SERVICE_STATUS svcStatus;
SC_HANDLE hManager, hService;
hManager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
if(!hManager) return 0;
hService = OpenService(hManager, SvcName, SERVICE_ALL_ACCESS);
if(!hService)
{
CloseServiceHandle(hManager);
return 0;
}
if(StartService(hService,0,0))
while(Cnt++ < 20)
{
QueryServiceStatus(hService, &svcStatus);
if(svcStatus.dwCurrentState == SERVICE_RUNNING) break;
else Sleep(250);
}
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
return (svcStatus.dwCurrentState == SERVICE_RUNNING);
}
/* ------------------------------------------------------------------------
* $Func AddServiceToGroupOrder
* Funktion: AddServiceToGroupOrder
* Aufgabe.: fuegt eine
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int AddServiceToGroupOrder(HINF hInf, /* handle der inf-datei */
char* SvcSection /* service-install-section */
)
{
int i;
HKEY hKey;
LONG Type, Size;
INFCONTEXT infCont;
char GrpOrder[1024], Group[256], GrpRel[256], * pGrpRel = 0;
if(!SetupFindFirstLine(hInf,SvcSection,"ServiceGroupOrder",&infCont))
return 1;
if(!SetupGetStringField(&infCont,1,Group,sizeof(Group),0)) return 0;
if(!SetupGetStringField(&infCont,2,GrpRel,sizeof(GrpRel),0)) GrpRel[0] = 0;
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\"
"Control\\ServiceGroupOrder",0,0,0,KEY_ALL_ACCESS,0,&hKey,&Type)
!= ERROR_SUCCESS) return 0;
Size = sizeof(GrpOrder);
if(RegQueryValueEx(hKey,"List",0,&Type,GrpOrder,&Size))
GrpOrder[0] = GrpOrder[1] = 0;
i = FindMultiString(GrpOrder, Group);
if(i >= 0) RemoveMultiString(GrpOrder, i);
pGrpRel = GrpRel;
if(GrpRel[0] == '+' || GrpRel[0] == '-') pGrpRel++;
i = FindMultiString(GrpOrder, pGrpRel);
if(i < 0) i = 0;
if(GrpRel[0] == '-') i = i ? i+1 : -1;
InsertMultiString(GrpOrder, Group, i);
RegSetValueEx(hKey, "List", 0,
REG_MULTI_SZ, GrpOrder, GetMultiStringLength(GrpOrder));
RegCloseKey(hKey);
return 1;
}
/* ------------------------------------------------------------------------
* $Func UpdateShortcuts
* Funktion: UpdateShortcuts
* Aufgabe.: bearbeitet 'MakeIcons' und 'DelIcons' aus einer section
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int UpdateShortcuts(HINF hInf, /* handle der inf-datei */
char* Section /* name der install-section */
)
{
int Sect;
INFCONTEXT infCont1, infCont2;
char SubSect[256], Where[16], Title[256], Exe[256],
Parms[256], Icon[256], IconIdx[256], Flags[256];
if(SetupFindFirstLine(hInf,Section,"MakeIcons",&infCont1))
{
Sect = 1;
while(SetupGetStringField(&infCont1,Sect++,SubSect,sizeof(SubSect),0))
{
if(!SetupFindFirstLine(hInf,SubSect,0,&infCont2)) continue;
do
{
if(!SetupGetStringField(&infCont2,1,Where,sizeof(Where),0)) continue;
if(!SetupGetStringField(&infCont2,2,Title,sizeof(Title),0)) continue;
if(!SetupGetStringField(&infCont2,3,Exe,sizeof(Exe),0)) continue;
if(!SetupGetStringField(&infCont2,4,Parms,sizeof(Parms),0))
Parms[0] = 0;
if(!SetupGetStringField(&infCont2,5,Icon,sizeof(Icon),0))
Icon[0] = 0;
if(!SetupGetStringField(&infCont2,6,IconIdx,sizeof(IconIdx),0))
IconIdx[0] = 0;
if(!SetupGetStringField(&infCont2,7,Flags,sizeof(Flags),0))
Flags[0] = 0;
CreateShortcut(Where, Title, Exe, Parms, Icon,
atoi(IconIdx), atoi(Flags));
}
while(SetupFindNextLine(&infCont2,&infCont2));
}
}
if(SetupFindFirstLine(hInf,Section,"DelIcons",&infCont1))
{
Sect = 1;
while(SetupGetStringField(&infCont1,Sect++,SubSect,sizeof(SubSect),0))
{
if(!SetupFindFirstLine(hInf,SubSect,0,&infCont2)) continue;
do
{
if(!SetupGetStringField(&infCont2,1,Where,sizeof(Where),0)) continue;
if(!SetupGetStringField(&infCont2,2,Title,sizeof(Title),0)) continue;
DeleteShortcut(Where, Title);
}
while(SetupFindNextLine(&infCont2,&infCont2));
}
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func CreateShortcut
* Funktion: CreateShortcut
* Aufgabe.: erzeugt einen link im start-menu
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int CreateShortcut(char* Where, /* wohin mit dem link */
char* Title, /* titel des links */
char* Exe, /* pfad und name der exe-datei */
char* Arguments, /* parameter */
char* Icon, /* icon-datei */
int IconIdx, /* icon-index */
int Flags /* enthaltenden ordner oeffnen */
)
{
char* c;
HRESULT hres;
IShellLink* psl;
WORD wLink[MAX_PATH];
char WorkPath[MAX_PATH], Link[MAX_PATH];
strcpy(WorkPath, Exe);
if(strrchr(WorkPath,'\\')) strrchr(WorkPath,'\\')[0] = 0;
CoInitialize(0);
hres = CoCreateInstance(&CLSID_ShellLink, 0,
CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl);
if(SUCCEEDED(hres))
{
IPersistFile* ppf;
psl->lpVtbl->SetPath(psl, Exe);
psl->lpVtbl->SetWorkingDirectory(psl, WorkPath);
psl->lpVtbl->SetArguments(psl, Arguments);
psl->lpVtbl->SetIconLocation(psl, Icon, IconIdx);
hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
if(SUCCEEDED(hres))
{
QueryStartMenuProgramFolder(Link, Where);
c = Link + strlen(Link);
strcat(Link, "\\");
strcat(Link, Title);
strcat(Link, ".lnk");
while(c = strchr(c+1,'\\'))
*c = 0, CreateDirectory(Link, 0), *c = '\\';
MultiByteToWideChar(CP_ACP, 0, Link, -1, wLink, MAX_PATH);
hres = ppf->lpVtbl->Save(ppf, wLink, TRUE);
ppf->lpVtbl->Release(ppf);
if(Flags)
{
if(strrchr(Link,'\\')) *strrchr(Link,'\\') = 0;
ShellExecute(0, 0, Link, 0, 0, SW_SHOWNA);
}
}
psl->lpVtbl->Release(psl);
}
CoUninitialize();
return SUCCEEDED(hres);
}
/* ------------------------------------------------------------------------
* $Func DeleteShortcut
* Funktion: DeleteShortcut
* Aufgabe.: erzeugt einen link im start-menu
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int DeleteShortcut(char* Where, /* wo ist der link */
char* Title) /* titel des links */
{
char Link[MAX_PATH], Path[MAX_PATH];
if(QueryStartMenuProgramFolder(Path,Where))
{
strcpy(Link, Path);
strcat(Link, "\\");
strcat(Link, Title);
strcat(Link, ".lnk");
DeleteFile(Link);
while(strrchr(Link,'\\'))
{
strrchr(Link,'\\')[0] = 0;
if(strlen(Link) <= strlen(Path)) break;
if(!RemoveDirectory(Link)) break;
}
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func DoExecStatements
* Funktion: DoExecStatements
* Aufgabe.: fuehrt exec-statements aus
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int DoExecStatements(HINF hInf, /* handle der inf-datei */
char* Section, /* install-section */
int InstallStep, /* installations-schritt */
HWND hwndOwner) /* owner fuer kind-prozesse */
{
int Sect;
INFCONTEXT infCont1, infCont2;
char SubSect[256], Step[16], Cmd[256], Arg[256],
WorkDir[256], Flags[16], Path[256];
if(SetupFindFirstLine(hInf,Section,"Exec",&infCont1))
{
Sect = 1;
while(SetupGetStringField(&infCont1,Sect++,SubSect,sizeof(SubSect),0))
{
if(SubSect[0] == '@') ExecuteCommand(SubSect+1, 0, 0, 0, hwndOwner);
else if(!SetupFindFirstLine(hInf,SubSect,0,&infCont2)) continue;
do
{
if(!SetupGetStringField(&infCont2,1,Step,sizeof(Step),0)) continue;
if(strtol(Step,0,0) != InstallStep) continue;
if(!SetupGetStringField(&infCont2,2,Cmd,sizeof(Cmd),0)) continue;
if(!SetupGetStringField(&infCont2,3,Arg,sizeof(Arg),0))
Arg[0] = 0;
if(!SetupGetStringField(&infCont2,4,WorkDir,sizeof(WorkDir),0))
WorkDir[0] = 0;
if(!SetupGetStringField(&infCont2,5,Flags,sizeof(Flags),0))
Flags[0] = 0;
GetCurrentDirectory(sizeof(Path), Path);
ExecuteCommand(Cmd, Arg, WorkDir, strtol(Flags,0,0), hwndOwner);
SetCurrentDirectory(Path);
}
while(SetupFindNextLine(&infCont2,&infCont2));
}
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func ExecuteCommand
* Funktion: ExecuteCommand
* Aufgabe.: fuehrt einen externen befehl durch
* Resultat: haengt von der notifcation ab
* Hinweis.:
* ------------------------------------------------------------------------ */
int ExecuteCommand(char* Cmd, /* befehl */
char* Arg, /* argumente */
char* WorkDir, /* arbeitsverzeichnis */
int Flags, /* weitere optionen */
HWND hwndOwner) /* owner fuer kind-prozesse */
{
SHELLEXECUTEINFO execInfo;
char cArg[1024], cHwnd[16], *pHlp;
strcpy(cArg, Arg);
sprintf(cHwnd, "0x%08x", hwndOwner);
while((pHlp = strchr(cArg,'%')) && !strnicmp(pHlp,"%hwnd%",6))
{
memmove(pHlp + strlen(cHwnd), pHlp + 6, strlen(pHlp+6) + 1);
strncpy(pHlp, cHwnd, strlen(cHwnd));
}
execInfo.cbSize = sizeof(execInfo);
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
execInfo.hwnd = GetDesktopWindow();
execInfo.lpVerb = 0;
execInfo.lpFile = Cmd;
execInfo.lpParameters = cArg;
execInfo.lpDirectory = WorkDir;
execInfo.nShow = SW_SHOWNORMAL;
if(!ShellExecuteEx(&execInfo)) return 0;
if(!execInfo.hProcess) return 0;
// Flags & 0x01 == do not wait for process
// Flags & 0x02 == delete file after executing, not in combination with 0x01
if(Flags & 0x01)
return 1;
WaitForSingleObject(execInfo.hProcess, INFINITE);
if(Flags & 0x02)
DeleteFile(Cmd);
return 1;
}
/* ------------------------------------------------------------------------
* $Func QueueCallback
* Funktion: QueueCallback
* Aufgabe.: callback-funktion fuer die file-queue
* Resultat: haengt von der notifcation ab
* Hinweis.:
* ------------------------------------------------------------------------ */
UINT WINAPI QueueCallback(VOID* Context, /* context-struktur */
UINT Notification, /* notification-code */
UINT Param1, /* zusaetzlicher parameter */
UINT Param2 /* zusaetzlicher parameter */
)
{
HANDLE hFind;
DWORD iResult;
FILEPATHS* pPath;
WIN32_FIND_DATA FindData;
int ZombieFiles, FileCnt;
void** pContext = (void**)Context;
char* pLastDir, CurrDir[MAX_PATH], * pHlp1, * pHlp2;
pLastDir = (char*)pContext[1];
ZombieFiles = (int)pContext[2];
switch(Notification)
{
case SPFILENOTIFY_STARTQUEUE:
pLastDir = (void*)malloc(MAX_PATH);
pLastDir[0] = 0;
break;
case SPFILENOTIFY_ENDQUEUE:
free(pLastDir);
break;
case SPFILENOTIFY_STARTCOPY:
pPath = (FILEPATHS*)Param1;
pHlp1 = strrchr(pPath->Source,'\\') ?
strrchr(pPath->Source,'\\') : pPath->Source;
pHlp2 = strrchr(pPath->Target,'\\') ?
strrchr(pPath->Target,'\\') : pPath->Target;
if(!stricmp(pHlp1,pHlp2))
{
pHlp1 = strrchr(pHlp1, '.');
pHlp2 = strrchr(pHlp2, '.');
if(pHlp1 && !stricmp(pHlp1,".cab") && pHlp2 && !stricmp(pHlp2,".cab"))
{
SetFileAttributes(pPath->Target, FILE_ATTRIBUTE_NORMAL);
iResult = CopyFile(pPath->Source, pPath->Target, 0);
SetFileAttributes(pPath->Target, FILE_ATTRIBUTE_NORMAL);
return iResult ? FILEOP_SKIP : FILEOP_ABORT;
}
}
break;
case SPFILENOTIFY_ENDDELETE:
pPath = (FILEPATHS*)Param1;
strcpy(CurrDir, pPath->Target);
if(strrchr(CurrDir,'\\')) strrchr(CurrDir,'\\')[0] = 0;
if(strcmp(CurrDir,pLastDir))
strcpy(pLastDir,CurrDir), ZombieFiles = 0;
hFind = FindFirstFile(pPath->Target, &FindData);
if(hFind != INVALID_HANDLE_VALUE)
{
FindClose(hFind);
Reboot = 1;
ZombieFiles++;
DelayFileDelete((char*)pPath->Target);
}
FileCnt = GetFileCount(CurrDir) - ZombieFiles;
if(!FileCnt && !RemoveDirectory(CurrDir)) DelayDirDelete(CurrDir);
break;
}
pContext[1] = (void*)pLastDir;
pContext[2] = (void*)ZombieFiles;
return SetupDefaultQueueCallback(pContext[0],Notification,Param1,Param2);
}
/* ------------------------------------------------------------------------
* $Func GetDefaultTargetPath
* Funktion: GetDefaultTargetPath
* Aufgabe.: liefert zielverzeichnis
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int GetDefaultTargetPath(HINF hInf, /* handle der inf-datei */
char* Path, /* ^puffer fuer pfad */
char* RelPath /* ^puffer fuer relativ-pfad */
)
{
int DirID = 0;
INFCONTEXT infCont;
char Buff[MAX_PATH] = "", Buff2[MAX_PATH] = "";
if(SetupFindFirstLine(hInf,"DestinationDirs","DefaultDestDir",&infCont))
{
SetupGetStringField(&infCont,1,Buff,sizeof(Buff),0);
SetupGetStringField(&infCont,2,Buff2,sizeof(Buff2),0);
DirID = atoi(Buff);
}
if(DirID == 24 && QueryApplPath(Buff))
{
strcpy(Path, Buff);
if(Path[strlen(Path)-1] != '\\') strcat(Path, "\\");
if(strlen(Buff2) && Buff2[0] == '\\') strcat(Path, Buff2+1);
else if(strlen(Buff2)) strcat(Path, Buff2);
if(Path[strlen(Path)-1] == '\\') Path[strlen(Path)-1] = 0;
if(RelPath) strcpy(RelPath, Buff2);
}
else
{
SetupGetTargetPath(hInf, 0, 0, Path, MAX_PATH, 0);
if(RelPath) strcpy(RelPath, Buff2);
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func QueryTargetPath
* Funktion: QueryTargetPath
* Aufgabe.: oeffnet dialog, in dem zielverzeichnis gewaehlt werden kann
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int QueryTargetPath(HWND hwnd, /* handle des owner-dialogs */
char* Path, /* puffer fuer pfad */
char* RelPath /* optional: relativ-pfad */
)
{
int rc;
LPMALLOC pIMalloc;
BROWSEINFO BrowseInfo;
ITEMIDLIST* pItemIdList;
char buff[MAX_PATH], buff2[MAX_PATH];
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
if(SHGetMalloc(&pIMalloc) != NOERROR) return 0;
LoadString(hInstance, STR_BROWSETITLE, buff, sizeof(buff));
BrowseInfo.hwndOwner = hwnd;
BrowseInfo.pidlRoot = 0;
BrowseInfo.pszDisplayName = buff2;
BrowseInfo.lpszTitle = buff;
BrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS;
BrowseInfo.lpfn = 0;
BrowseInfo.lParam = 0;
BrowseInfo.iImage = 0;
pItemIdList = (ITEMIDLIST*)SHBrowseForFolder(&BrowseInfo);
if(pItemIdList)
{
rc = SHGetPathFromIDList(pItemIdList,Path);
pIMalloc->lpVtbl->Free(pIMalloc, pItemIdList);
pIMalloc->lpVtbl->Release(pIMalloc);
if(!rc) return 0;
if(!RelPath) return 1;
if(RelPath[0] == '\\') RelPath++;
if(!strlen(RelPath)) return 1;
if(strrchr(Path,'\\') && !strcmp(strrchr(Path,'\\')+1,RelPath))
return 1;
if(Path[strlen(Path)-1] != '\\') strcat(Path, "\\");
strcat(Path, RelPath);
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func QueryApplPath
* Funktion: QueryApplPath
* Aufgabe.: liefert den pfad des applikations-verzeichnisses
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int QueryApplPath(char* Path) /* puffer fuer den pfad */
{
int rc;
HKEY key;
LONG type;
LONG buffsize;
char buff[MAX_PATH];
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\"
"CurrentVersion",0,KEY_READ,&key) != ERROR_SUCCESS) return 0;
buffsize = sizeof(buff);
rc = RegQueryValueEx(key, "ProgramFilesDir", 0, &type, buff, &buffsize);
RegCloseKey(key);
if(rc != ERROR_SUCCESS) return 0;
if(type == REG_EXPAND_SZ)
ExpandEnvironmentStrings(buff, Path, MAX_PATH);
else if(type == REG_SZ)
strncpy(Path, buff, MAX_PATH-1), Path[MAX_PATH-1] = 0;
else return 0;
return 1;
}
/* ------------------------------------------------------------------------
* $Func QueryStartMenuProgramFolder
* Funktion: QueryStartMenuProgramFolder
* Aufgabe.: liefert den pfad des Programm-Ordners im Start-Menue
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int QueryStartMenuProgramFolder(char* Path, /* puffer fuer den pfad */
char* Where /* wo */
)
{
int rc;
char buff[256];
LONG type, buffsize;
HKEY hKeyCU = 0, hKeyLM = 0;
RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows"
"\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_READ, &hKeyCU);
RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows"
"\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_READ, &hKeyLM);
if(!hKeyCU && !hKeyLM) return 0;
buffsize = sizeof(buff);
if(!stricmp(Where,"CDSK"))
{
if(hKeyLM)
rc = RegQueryValueEx(hKeyLM, "Common Desktop", 0, &type, buff, &buffsize);
if(!hKeyLM || (rc != ERROR_SUCCESS && hKeyCU))
rc = RegQueryValueEx(hKeyCU, "Desktop", 0, &type, buff, &buffsize);
}
else if(!stricmp(Where,"CPRG"))
{
if(hKeyLM)
rc = RegQueryValueEx(hKeyLM, "Common Programs", 0, &type, buff, &buffsize);
if(!hKeyLM || (rc != ERROR_SUCCESS && hKeyCU))
rc = RegQueryValueEx(hKeyCU, "Programs", 0, &type, buff, &buffsize);
}
else if(!stricmp(Where,"CSTM"))
{
if(hKeyLM)
rc = RegQueryValueEx(hKeyLM, "Common Start Menu", 0, &type, buff, &buffsize);
if(!hKeyLM || (rc != ERROR_SUCCESS && hKeyCU))
rc = RegQueryValueEx(hKeyCU, "Start Menu", 0, &type, buff, &buffsize);
}
else if(!stricmp(Where,"CSTU"))
{
if(hKeyLM)
rc = RegQueryValueEx(hKeyLM, "Common Startup", 0, &type, buff, &buffsize);
if(!hKeyLM || (rc != ERROR_SUCCESS && hKeyCU))
rc = RegQueryValueEx(hKeyCU, "Startup", 0, &type, buff, &buffsize);
}
else if(!stricmp(Where,"UDSK"))
{
if(hKeyCU)
rc = RegQueryValueEx(hKeyCU, "Desktop", 0, &type, buff, &buffsize);
}
else if(!stricmp(Where,"UPRG"))
{
if(hKeyCU)
rc = RegQueryValueEx(hKeyCU, "Programs", 0, &type, buff, &buffsize);
}
else if(!stricmp(Where,"USTM"))
{
if(hKeyCU)
rc = RegQueryValueEx(hKeyCU, "Start Menu", 0, &type, buff, &buffsize);
}
else if(!stricmp(Where,"USTU"))
{
if(hKeyCU)
rc = RegQueryValueEx(hKeyCU, "Startup", 0, &type, buff, &buffsize);
}
else rc = !ERROR_SUCCESS;
if(hKeyCU) RegCloseKey(hKeyCU);
if(hKeyLM) RegCloseKey(hKeyLM);
if(rc != ERROR_SUCCESS) return 0;
if(type == REG_SZ)
{
strncpy(Path, buff, MAX_PATH-1);
Path[MAX_PATH-1] = 0;
return 1;
}
if(type == REG_EXPAND_SZ)
{
ExpandEnvironmentStrings(buff,Path,MAX_PATH);
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func QuerySetupExePath
* Funktion: QuerySetupExePath
* Aufgabe.: liefert den pfad zur installierten setup.exe
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int QuerySetupExePath(HINF hInf, /* handle der inf-datei */
char* Section, /* install-section */
char* Path /* puffer fuer pfad */
)
{
int Idx = 1;
char CopySect[256], File[256];
INFCONTEXT infCont1, infCont2;
if(SetupFindFirstLine(hInf,Section,"CopyFiles",&infCont1))
{
while(SetupGetStringField(&infCont1,Idx++,CopySect,sizeof(CopySect),0))
{
if(!SetupFindFirstLine(hInf,CopySect,0,&infCont2)) continue;
do
{
if(!SetupGetStringField(&infCont2,1,File,sizeof(File),0)) continue;
if(stricmp(File,EXENAME)) continue;
if(SetupGetTargetPath(hInf,&infCont2,0,Path,MAX_PATH,0))
{
strcat(Path,"\\");
strcat(Path,EXENAME);
return 1;
}
}
while(SetupFindNextLine(&infCont2,&infCont2));
}
}
return 0;
}
/* ------------------------------------------------------------------------
* $Func GetFileCount
* Funktion: GetFileCount
* Aufgabe.: zaehlt dateien in einem verzeichnis
* Resultat: anzahl dateien
* Hinweis.:
* ------------------------------------------------------------------------ */
int GetFileCount(char* Path) /* verzeichnis-name */
{
int Cnt = 0;
HANDLE hFind;
char Buff[MAX_PATH];
WIN32_FIND_DATA Find;
sprintf(Buff, "%s\\*", Path);
hFind = FindFirstFile(Buff,&Find);
if(hFind == INVALID_HANDLE_VALUE) return 0;
do
{
if(Find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
else Cnt++;
}
while(FindNextFile(hFind,&Find));
FindClose(hFind);
return Cnt;
}
/* ------------------------------------------------------------------------
* $Func DelayFileDelete
* Funktion: DelayFileDelete
* Aufgabe.: markiert eine datei zum loeschen beim naechsten systemstart
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int DelayFileDelete(char* File) /* datei-name */
{
int Size;
char Ini[256];
char Name[256];
char Buff[1024];
if(IS_WINNT) MoveFileEx(File, 0, MOVEFILE_DELAY_UNTIL_REBOOT);
else
{
GetWindowsDirectory(Ini, sizeof(Ini));
strcat(Ini, "\\wininit.ini");
GetShortPathName(File, Name, sizeof(Name));
Size = GetPrivateProfileSection("Rename", Buff, sizeof(Buff), Ini);
sprintf(Buff + Size, "NUL=%s%c", Name, 0);
WritePrivateProfileSection("Rename", Buff, Ini);
}
return 1;
}
/* ------------------------------------------------------------------------
* $Func DelayDirDelete
* Funktion: DelayDirDelete
* Aufgabe.: markiert ein verzeichnis zum loeschen beim naechsten systemstart
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int DelayDirDelete(char* Dir) /* verzeichnis-name */
{
if(IS_WINNT) MoveFileEx(Dir, 0, MOVEFILE_DELAY_UNTIL_REBOOT);
else return 0; /* unter 95 nicht moeglich */
return 1;
}
/* ------------------------------------------------------------------------
* $Func CenterWindow
* Funktion: CenterWindow
* Aufgabe.: zentriert ein fenster relativ zu einem anderen.
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int CenterWindow(HWND hwndChild, /* zu zentrierendes fenster */
HWND hwndParent /* relatives fenster */
)
{
int xNew, yNew;
int wChild, hChild, wParent, hParent;
RECT rChild, rParent, rWorkArea;
if(!GetWindowRect(hwndChild,&rChild)) return 0;
wChild = rChild.right - rChild.left;
hChild = rChild.bottom - rChild.top;
if(!GetWindowRect(hwndParent,&rParent))
GetWindowRect(GetDesktopWindow(),&rParent);
wParent = rParent.right - rParent.left;
hParent = rParent.bottom - rParent.top;
if(!SystemParametersInfo(SPI_GETWORKAREA,
sizeof(rWorkArea), &rWorkArea, 0))
{
rWorkArea.left = rWorkArea.top = 0;
rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
}
xNew = rParent.left + ((wParent - wChild) / 2);
if(xNew < rWorkArea.left) xNew = rWorkArea.left;
else if((xNew+wChild) > rWorkArea.right) xNew = rWorkArea.right - wChild;
yNew = rParent.top + ((hParent - hChild) / 2);
if(yNew < rWorkArea.top) yNew = rWorkArea.top;
else if ((yNew+hChild) > rWorkArea.bottom) yNew = rWorkArea.bottom - hChild;
return SetWindowPos(hwndChild,0,xNew,yNew,0,0,SWP_NOSIZE|SWP_NOZORDER);
}
/* ------------------------------------------------------------------------
* $Func EnumResLangProc
* Funktion: EnumResLangProc
* Aufgabe.: callback-funktion fuer GetResourceLanguages
* Resultat: immer TRUE
* Hinweis.:
* ------------------------------------------------------------------------ */
BOOL EnumResLangProc(HANDLE hModule, /* resource-module handle */
LPCTSTR lpszType, /* zeiger auf resource-typ */
LPCTSTR lpszName, /* zeiger auf resource-name */
WORD wIDLanguage, /* microsoft language-ID */
LONG lParam /* von EnumResourceLanguages */
)
{
(*((LANGID**)lParam))[0] = wIDLanguage;
(*((LANGID**)lParam))[1] = 0;
(*((LANGID**)lParam))++;
return 1;
}
/* ------------------------------------------------------------------------
* $Func GetResourceLanguages
* Funktion: GetResourceLanguages
* Aufgabe.: liefert alle sprachen, die in den resourcen verfuegbar sind
* Resultat: vektor von LANGID's, das ende wird durch 0 gekennzeichnet
* Hinweis.:
* ------------------------------------------------------------------------ */
LANGID* GetResourceLanguages(char* res_id /* resource-name oder -id */
)
{
static LANGID lang[256];
LANGID* pLang = lang;
lang[0] = 0;
EnumResourceLanguages(0, RT_DIALOG, res_id,
(ENUMRESLANGPROC)EnumResLangProc, (LONG)&pLang);
return lang;
}
/* ------------------------------------------------------------------------
* $Func GetSystemLanguage
* Funktion: GetSystemLanguage
* Aufgabe.: liefert die sprache der installierten windows-version
* Resultat: LANGID: microsoft-language-identifier
* Hinweis.: die sprache hat nichts mit dem land zu tun, das als 'current
* locale' im control-panel eingestellt ist! es ist lediglich die
* sprache der windows-installation.
* ------------------------------------------------------------------------ */
LANGID GetSystemLanguage()
{
HKEY hKey;
LANGID iLangID;
char cLocale[16];
HINSTANCE hKrnlDll;
int iResult, iType, iSize;
LANGID (APIENTRY *GetUserDefaultUILanguage)(void);
iLangID = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
if(IS_WIN2K)
{
hKrnlDll = LoadLibrary("kernel32.dll");
if(!hKrnlDll) return iLangID;
GetUserDefaultUILanguage = (LANGID(APIENTRY*)(void))
GetProcAddress(hKrnlDll, "GetUserDefaultUILanguage");
if(!GetUserDefaultUILanguage)
{
FreeLibrary(hKrnlDll);
return iLangID;
}
iLangID = GetUserDefaultUILanguage();
}
else if(IS_WINNT)
{
iResult = RegOpenKeyEx(HKEY_USERS,
".DEFAULT\\Control Panel\\International", 0, KEY_READ, &hKey);
if(iResult == ERROR_SUCCESS)
{
iSize = sizeof(cLocale);
iResult = RegQueryValueEx(hKey, "Locale", 0, &iType, cLocale, &iSize);
if(iResult == ERROR_SUCCESS && iType == REG_SZ)
iLangID = LANGIDFROMLCID(strtoul(cLocale,0,16));
RegCloseKey(hKey);
}
}
else
{
iResult = RegOpenKeyEx(HKEY_CURRENT_USER,
"Control Panel\\Desktop\\ResourceLocale", 0, KEY_READ, &hKey);
if(iResult == ERROR_SUCCESS)
{
iSize = sizeof(cLocale);
iResult = RegQueryValueEx(hKey, 0, 0, &iType, cLocale, &iSize);
if(iResult == ERROR_SUCCESS && iType == REG_SZ)
iLangID = LANGIDFROMLCID(strtoul(cLocale,0,16));
RegCloseKey(hKey);
}
}
return iLangID;
}
/* ------------------------------------------------------------------------
* $Func GetDefaultLanguage
* Funktion: GetDefaultLanguage
* Aufgabe.: liefert einen default-wert fuer die sprache des programms
* Resultat: LANGID: microsoft language-identifier
* Hinweis.: der default-wert wird abhaengig von der sprache der
* installierten windows-version und den verfuegbaren sprachen
* in den resourcen gewaehlt
* ------------------------------------------------------------------------ */
LANGID GetDefaultLanguage(char* res_id) /* resource-name oder -id */
{
int i;
LANGID DefLang;
LANGID* pResLang;
DefLang = GetSystemLanguage();
pResLang = GetResourceLanguages(res_id);
for(i = 0; pResLang[i]; i++)
if(pResLang[i] == DefLang)
return pResLang[i];
for(i = 0; pResLang[i]; i++)
if(PRIMARYLANGID(pResLang[i]) == PRIMARYLANGID(DefLang))
return pResLang[i];
return MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
}
/* ------------------------------------------------------------------------
* $Func GetMultiString
* Funktion: GetMultiString
* Aufgabe.: holt einen string aus mehreren aufeinanderfolgenden strings
* Resultat: zeiger auf den gesuchten string
* Hinweis.:
* ------------------------------------------------------------------------ */
char* GetMultiString(const char* c, /* zeiger auf mehrere strings */
int index) /* indes des gesuchten strings */
{
if(!c) return 0;
while(index--)
{
c += strlen(c) + 1;
if(!*c) return 0;
}
return (char*)c;
}
/* ------------------------------------------------------------------------
* $Func InsertMultiString
* Funktion: InsertMultiString
* Aufgabe.: fuegt einen string in einen multi-string ein
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int InsertMultiString(char* c, /* zeiger auf mehrere strings */
char* s, /* einzufuegender string */
int index) /* index zum einfuegen */
{
if(index < 0) index = CountMultiStrings(c);
while(index--)
{
c += strlen(c) + 1;
if(!*c) break;
}
memmove(c+strlen(s)+1, c, GetMultiStringLength(c));
memcpy(c, s, strlen(s)+1);
return 1;
}
/* ------------------------------------------------------------------------
* $Func RemoveMultiString
* Funktion: RemoveMultiString
* Aufgabe.: loescht einen string aus einen multi-string
* Resultat: TRUE wenn erfolgreich
* Hinweis.:
* ------------------------------------------------------------------------ */
int RemoveMultiString(char* c, /* zeiger auf mehrere strings */
int index) /* index zum loeschen */
{
char* p;
c = GetMultiString(c, index);
if(!c) return 0;
p = c + strlen(c) + 1;
memmove(c, p, GetMultiStringLength(p));
return 1;
}
/* ------------------------------------------------------------------------
* $Func CountMultiStrings
* Funktion: CountMultiStrings
* Aufgabe.: zaehlt mehrere aufeinaderfolgende strings
* Resultat: anzahl strings
* Hinweis.:
* ------------------------------------------------------------------------ */
int CountMultiStrings(const char* c)
{
int count = 0;
while(GetMultiString(c,count)) count++;
return count;
}
/* ------------------------------------------------------------------------
* $Func FindMultiString
* Funktion: FindMultiString
* Aufgabe.: sucht in einem multi-string nach einem bestimmten string
* Resultat: index wenn gefunden, sonst -1
* Hinweis.:
* ------------------------------------------------------------------------ */
int FindMultiString(const char* c, /* zeiger auf multi-string */
const char* s /* zu suchender string */
)
{
const char* p;
int index = 0;
while(p = GetMultiString(c,index))
if(!strcmp(p,s)) return index;
else index++;
return -1;
}
/* ------------------------------------------------------------------------
* $Func GetMultiStringLength
* Funktion: GetMultiStringLength
* Aufgabe.: ermittelt die gesammt-laenge eines multi-string
* Resultat: gesamtlaenge aller strings mit allen null-terminatoren
* Hinweis.:
* ------------------------------------------------------------------------ */
int GetMultiStringLength(const char* c) /* zeiger auf multi-string */
{
const char* p = c;
if(!*p) p++;
else while(*p) p += strlen(p)+1;
return (p-c)+1;
}
/* ------------------------------------------------------------------------
* $Func GetComCtlVersion
* Funktion: GetComCtlVersion
* Aufgabe.: version von comctl32.dll abfragen
* Resultat: keins
* Hinweis.:
* ------------------------------------------------------------------------ */
int GetComCtlVersion(DWORD* pMajor, DWORD* pMinor)
{
HINSTANCE hComCtl;
DWORD VerInf[5];
FARPROC DllGetVersion;
memset(&VerInf, 0, sizeof(VerInf));
VerInf[0] = sizeof(VerInf);
hComCtl = LoadLibrary("comctl32.dll");
if(!hComCtl) return 0;
DllGetVersion = GetProcAddress(hComCtl, "DllGetVersion");
if(!DllGetVersion || DllGetVersion(&VerInf))
*pMajor = 4, *pMinor = 0;
else
*pMajor = VerInf[1], *pMinor = VerInf[2];
FreeLibrary(hComCtl);
return 1;
}
/* ------------------------------------------------------------------------
* $Func ErrorMessageBox
* Funktion: ErrorMessageBox
* Aufgabe.: zeigt eine message-box mit beschreibung eines api-errors an
* ------------------------------------------------------------------------ */
int ErrorMessageBox(HWND hwndOwner, /* owner-window */
char* pText, /* fehler-text */
int iErrCode) /* von GetLastError() */
{
char* pMsg;
char cText[256];
if(iErrCode)
{
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
0, iErrCode, AppLang, (char*)&pMsg, 0, 0);
sprintf(cText, "%s\r\n\r\n%s", pText, pMsg);
LocalFree(pMsg);
}
else strcpy(cText, pText);
MessageBox(hwndOwner, cText, 0, MB_OK|MB_ICONERROR);
return 0;
}
/* ------------------------------------------------------------------------
* @Function: MakeWizardBmp
* @Info : Erzeugt Watermark/Header-Bitmap fuer den Wizard97
* @Result : handle des neuen Bitmaps
* ------------------------------------------------------------------------ */
HBITMAP MakeWizardBmp(HWND hwnd, /* irgendein fenster-handle */
HBITMAP hBmpOrg, /* original-wizard-bitmap */
int iSizeX, /* hoehe des neuen bitmaps */
int iSizeY, /* breite des neuen bitmaps */
int iOffsX, /* position des wizard-bitmaps */
int iOffsY) /* position des wizard-bitmaps */
{
RECT sRcHlp;
BITMAP sBmp;
HBITMAP hBmpNew;
HGDIOBJ hOldObj1, hOldObj2;
HDC hDcWnd, hDcTmp1, hDcTmp2;
GetObject(hBmpOrg, sizeof(sBmp), &sBmp); /* groesse des original-bitmaps */
hDcWnd = GetDC(hwnd); /* fenster-dc holen */
hDcTmp1 = CreateCompatibleDC(hDcWnd); /* zwei kompatible temporaer- */
hDcTmp2 = CreateCompatibleDC(hDcWnd); /* dc's erzeugen */
hBmpNew = CreateCompatibleBitmap(hDcWnd, /* neues bitmap in der */
iSizeX, iSizeY); /* gefordeten groesse erzeugen */
hOldObj1 = SelectObject(hDcTmp1,hBmpNew); /* quell- und ziel-bitmap in */
hOldObj2 = SelectObject(hDcTmp2,hBmpOrg); /* die temp-dc's selektieren */
sRcHlp.left = sRcHlp.top = 0; /* rect-struktur mit kompleter */
sRcHlp.right = iSizeX; /* groesse des neuen bitmaps */
sRcHlp.bottom = iSizeY; /* initialisieren */
FillRect(hDcTmp1, &sRcHlp, (HBRUSH)(COLOR_WINDOW+1)); /* rechteck fuellen */
BitBlt(hDcTmp1, iOffsX, iOffsY, sBmp.bmWidth, /* org-bmp an gewuenschte */
sBmp.bmHeight, hDcTmp2, 0, 0, SRCCOPY); /* position blitten */
SelectObject(hDcTmp1, hOldObj1); /* temporaer-dc's saubermachen */
SelectObject(hDcTmp2, hOldObj2);
DeleteDC(hDcTmp1); /* temporaer-dc's loeschen */
DeleteDC(hDcTmp2);
ReleaseDC(hwnd, hDcWnd); /* fenster-dc freigeben */
return hBmpNew;
}
/* ------------------------------------------------------------------------
* @Function: InitWizardData
* @Info : Laedt diverse Resourcen (Icons, Fonts, Texte) fuer den Wizard
* @Result : TRUE wenn erfolgreich
* ------------------------------------------------------------------------ */
int InitWizardData(HINSTANCE hInstance, tWizardData* pData)
{
HDC hDc;
LOGFONT sFont;
int iLogPixelsY;
hDc = GetDC(0);
iLogPixelsY = GetDeviceCaps(hDc, LOGPIXELSY);
ReleaseDC(0, hDc);
memset(&sFont, 0, sizeof(sFont));
strcpy(sFont.lfFaceName, "MS Shell Dlg");
sFont.lfWeight = FW_BOLD;
sFont.lfHeight = 0 - MulDiv(12, iLogPixelsY, 72);
pData->hWelcomeTitleFont = CreateFontIndirect(&sFont);
sFont.lfHeight = 0 - MulDiv(8, iLogPixelsY, 72);
pData->hHeaderTitleFont = CreateFontIndirect(&sFont);
pData->hImgLst = ImageList_LoadBitmap(hInstance,
MAKEINTRESOURCE(ID_BMPLIST), 16, 0, 0x00808000);
pData->hSmInfoIcon = ImageList_GetIcon(pData->hImgLst, 70, ILD_NORMAL);
pData->hSmAlertIcon = ImageList_GetIcon(pData->hImgLst, 69, ILD_NORMAL);
LoadString(hInstance, STR_INSTALLTITLE,
pData->cWelcomeTitle, sizeof(pData->cWelcomeTitle));
LoadString(hInstance, STR_INSTALLTEXT,
pData->cWelcomeText, sizeof(pData->cWelcomeText));
LoadString(hInstance, STR_WIZ97_P2TITLE,
pData->cPage2HdrTitle, sizeof(pData->cPage2HdrTitle));
LoadString(hInstance, STR_WIZ97_P2SUBTITLE,
pData->cPage2HdrSubTitle, sizeof(pData->cPage2HdrSubTitle));
LoadString(hInstance, STR_WIZ97_P3TITLE,
pData->cPage3HdrTitle, sizeof(pData->cPage3HdrTitle));
LoadString(hInstance, STR_WIZ97_P3SUBTITLE,
pData->cPage3HdrSubTitle, sizeof(pData->cPage3HdrSubTitle));
LoadString(hInstance, STR_WIZ97_P4TITLE,
pData->cPage4HdrTitle, sizeof(pData->cPage4HdrTitle));
LoadString(hInstance, STR_WIZ97_P4SUBTITLE,
pData->cPage4HdrSubTitle, sizeof(pData->cPage4HdrSubTitle));
return 1;
}
/* ------------------------------------------------------------------------
* @Function: FreeWizardData
* @Info : Gibt von InitWizardData() geladene Resourcen wieder frei
* @Result : TRUE wenn erfolgreich
* ------------------------------------------------------------------------ */
int FreeWizardData(tWizardData* pData)
{
DestroyIcon(pData->hSmInfoIcon);
DestroyIcon(pData->hSmAlertIcon);
ImageList_Destroy(pData->hImgLst);
DeleteObject(pData->hWelcomeTitleFont);
DeleteObject(pData->hHeaderTitleFont);
return 1;
}
/* ------------------------------------------------------------------------
* @Function: LoadDlgTemplate
* @Info : Laedt eine Dialog-Resource und kopiert sie in den Speicher
* @Result : Zeiger auf DLGTEMPLATE
* ------------------------------------------------------------------------ */
DLGTEMPLATE* LoadDlgTemplate(HINSTANCE hInstance, char* pszTemplate)
{
HRSRC hRes;
UINT iResLen;
char* pResData;
DLGTEMPLATE* pDlgTemplate;
hRes = FindResource(hInstance, pszTemplate, RT_DIALOG);
if(!hRes) return 0;
iResLen = SizeofResource(hInstance, hRes);
pResData = (char*)LockResource(LoadResource(hInstance,hRes));
if(!pResData || !iResLen)
return 0;
pDlgTemplate = (DLGTEMPLATE*)malloc(iResLen);
memcpy(pDlgTemplate, pResData, iResLen);
return pDlgTemplate;
}
/* ------------------------------------------------------------------------
* @Function: FreeDlgTemplate
* @Info : Gibt den von LoadDlgTemplate() allokierten Speicher frei
* @Result : keins
* ------------------------------------------------------------------------ */
void FreeDlgTemplate(DLGTEMPLATE* pDlgTemplate)
{
free(pDlgTemplate);
}