tCheck for admin rights added to Win32 installer; error handling cleaned up; op… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit ed7fb9cd1a09f667ebc6fb3fcd07a684bca1d1aa | |
parent dc982dd81a76f2a8fcc599bdfe23552a230638de | |
Author: Ben Webb <[email protected]> | |
Date: Sun, 3 Feb 2002 20:20:07 +0000 | |
Check for admin rights added to Win32 installer; error handling cleaned up; | |
option to install in user's own Start Menu or the "all users" Start Menu added | |
Diffstat: | |
M ChangeLog | 1 + | |
M TODO | 1 - | |
M win32/contid.h | 2 ++ | |
M win32/dialogs.rc | 6 ++++-- | |
M win32/setup.c | 143 +++++++++++++++++++++++------… | |
M win32/uninstall.c | 2 +- | |
M win32/util.c | 34 ++++++++++++++++++++++++++---… | |
M win32/util.h | 10 ++++++++-- | |
8 files changed, 154 insertions(+), 45 deletions(-) | |
--- | |
diff --git a/ChangeLog b/ChangeLog | |
t@@ -12,6 +12,7 @@ cvs | |
- Keyboard shortcuts for menu items in Windows client | |
- Default buttons (ENTER -> "OK") for Windows client | |
- RPM build/make install can now be run as non-superuser | |
+ - Win32 install for current user/all users | |
- Code cleanups | |
1.5.2 16-10-2001 | |
diff --git a/TODO b/TODO | |
t@@ -1,4 +1,3 @@ | |
-- Win32 install for current user/all users | |
- Test code under Win98 | |
- Document new server interface | |
- Admin of running NT Service servers | |
diff --git a/win32/contid.h b/win32/contid.h | |
t@@ -14,3 +14,5 @@ | |
#define ST_DELSTAT 214 | |
#define ST_DELDONE 215 | |
#define BT_DELOK 216 | |
+#define RB_ALLUSERS 217 | |
+#define RB_ONEUSER 218 | |
diff --git a/win32/dialogs.rc b/win32/dialogs.rc | |
t@@ -8,8 +8,10 @@ BEGIN | |
PUSHBUTTON "&Next >", BT_NEXT, 144, 143, 39, 13, WS_CHILD | WS_VISIBLE… | |
PUSHBUTTON "Cancel", BT_CANCEL, 191, 143, 39, 13, WS_CHILD | WS_VISIBL… | |
LTEXT "Welcome to the dopewars-1.5.3 installation program.\nThis progr… | |
- LTEXT "Use the ""Back"" and ""Next"" buttons at the bottom of the dial… | |
- LTEXT "Newer versions of this program, when available, can be obtained… | |
+ LTEXT "Use the ""Back"" and ""Next"" buttons at the bottom of the dial… | |
+ LTEXT "Newer versions of this program, when available, can be obtained… | |
+ CONTROL "Install for &all users (requires admin rights)", RB_ALLUSERS,… | |
+ CONTROL "Install for ¤t user only", RB_ONEUSER, "BUTTON", BS_AUT… | |
END | |
2 DIALOG 17, 40, 239, 162 | |
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | |
diff --git a/win32/setup.c b/win32/setup.c | |
t@@ -40,24 +40,31 @@ HWND mainDlg[DL_NUM]; | |
DialogType CurrentDialog; | |
HINSTANCE hInst=NULL; | |
char *oldversion=NULL; | |
+BOOL services_supported, have_admin_rights, install_all_users; | |
DWORD WINAPI DoInstall(LPVOID lpParam); | |
static void GetWinText(char **text,HWND hWnd); | |
+static void FillFolderList(void); | |
-/* Returns TRUE if this operating system version supports NT Services */ | |
-BOOL ServicesSupported(void) { | |
+/* Does this OS version support NT services? If so, do we have the | |
+ * necessary (administrator) rights to use them? | |
+ */ | |
+void ServiceCheck(BOOL *hasServices, BOOL *isAdmin) { | |
SC_HANDLE scManager; | |
- scManager = OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT); | |
+ scManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE); | |
if (scManager) { | |
+ *hasServices = *isAdmin = TRUE; | |
CloseServiceHandle(scManager); | |
} else if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) { | |
- return FALSE; | |
+ *hasServices = *isAdmin = FALSE; | |
+ } else { | |
+ *hasServices = TRUE; | |
+ *isAdmin = FALSE; | |
} | |
- return TRUE; | |
} | |
-void InstallService(InstData *idata) { | |
+BOOL InstallService(InstData *idata) { | |
SC_HANDLE scManager,scService; | |
HKEY key; | |
bstr *str; | |
t@@ -65,13 +72,13 @@ void InstallService(InstData *idata) { | |
NTService *service; | |
service = idata->service; | |
- if (!service) return; | |
+ if (!service) return FALSE; | |
- scManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); | |
+ scManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE); | |
if (!scManager) { | |
DisplayError("Cannot connect to service manager",TRUE,FALSE); | |
- return; | |
+ return FALSE; | |
} | |
str = bstr_new(); | |
t@@ -85,7 +92,7 @@ void InstallService(InstData *idata) { | |
if (!scService) { | |
DisplayError("Cannot create service",TRUE,FALSE); | |
bstr_free(str,TRUE); | |
- return; | |
+ return FALSE; | |
} | |
bstr_assign(str,keyprefix); | |
t@@ -99,6 +106,7 @@ void InstallService(InstData *idata) { | |
CloseServiceHandle(scService); | |
CloseServiceHandle(scManager); | |
+ return TRUE; | |
} | |
BOOL CheckCreateDir(void) { | |
t@@ -117,7 +125,7 @@ BOOL CheckCreateDir(void) { | |
if (CreateWholeDirectory(instdir)) { | |
return TRUE; | |
} else { | |
- DisplayError("Could not create directory",FALSE,FALSE); | |
+ DisplayError("Could not create directory",TRUE,FALSE); | |
} | |
} | |
return FALSE; | |
t@@ -132,8 +140,20 @@ void ShowNewDialog(DialogType NewDialog) { | |
DWORD threadID; | |
if (NewDialog<0 || NewDialog>=DL_NUM) return; | |
- if (NewDialog > CurrentDialog && CurrentDialog==DL_INSTALLDIR) { | |
- if (!CheckCreateDir()) return; | |
+ if (NewDialog > CurrentDialog) { | |
+ switch(CurrentDialog) { | |
+ case DL_INSTALLDIR: | |
+ if (!CheckCreateDir()) return; | |
+ break; | |
+ case DL_INTRO: | |
+ install_all_users = (services_supported | |
+ && IsDlgButtonChecked(mainDlg[DL_INTRO], | |
+ RB_ALLUSERS)==BST_CHECKED); | |
+ FillFolderList(); | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
} | |
hWnd=mainDlg[NewDialog]; | |
t@@ -253,13 +273,13 @@ LPVOID GetResource(LPCTSTR resname,LPCTSTR restype) { | |
LPVOID respt; | |
hrsrc = FindResource(NULL,resname,restype); | |
- if (!hrsrc) DisplayError("Could not find resource: ",TRUE,TRUE); | |
+ if (!hrsrc) DisplayError("Could not find resource",TRUE,TRUE); | |
hglobal = LoadResource(NULL,hrsrc); | |
- if (!hglobal) DisplayError("Could not load resource: ",TRUE,TRUE); | |
+ if (!hglobal) DisplayError("Could not load resource",TRUE,TRUE); | |
respt = LockResource(hglobal); | |
- if (!respt) DisplayError("Could not lock resource: ",TRUE,TRUE); | |
+ if (!respt) DisplayError("Could not lock resource",TRUE,TRUE); | |
return respt; | |
} | |
t@@ -277,6 +297,7 @@ InstData *ReadInstData() { | |
pt=instdata; | |
idata = bmalloc(sizeof(InstData)); | |
+ idata->flags = 0; | |
idata->service = NULL; | |
idata->totalsize = atol(pt); | |
pt += strlen(pt)+1; | |
t@@ -515,16 +536,19 @@ void SetupShortcuts(HANDLE fout) { | |
char *startmenu,*desktop; | |
BOOL dodesktop; | |
- startmenu = GetStartMenuDir(idata); | |
+ startmenu = GetStartMenuDir(install_all_users, idata); | |
desktop = GetDesktopDir(); | |
dodesktop=(IsDlgButtonChecked(mainDlg[DL_SHORTCUTS],CB_DESKTOP)==BST_CHECKED… | |
if (startmenu) { | |
- CreateDirectory(startmenu,NULL); | |
- | |
- CreateLinks(startmenu,idata->startmenu); | |
- WriteLinkList(fout,idata->startmenu); | |
+ if (CreateDirectory(startmenu,NULL)) { | |
+ CreateLinks(startmenu,idata->startmenu); | |
+ WriteLinkList(fout,idata->startmenu); | |
+ } else { | |
+ DisplayError("Could not create Start Menu directory",TRUE,FALSE); | |
+ WriteLinkList(fout,NULL); | |
+ } | |
} else { | |
WriteLinkList(fout,NULL); | |
} | |
t@@ -564,7 +588,7 @@ void SetupUninstall() { | |
bstr_appendpath(str,idata->product); | |
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,str->text,0,NULL,0, | |
- KEY_ALL_ACCESS,NULL,&key,&disp)==ERROR_SUCCESS) { | |
+ KEY_WRITE,NULL,&key,&disp)==ERROR_SUCCESS) { | |
RegSetValueEx(key,"DisplayName",0,REG_SZ,idata->product, | |
strlen(idata->product)); | |
bstr_assign_windir(str); | |
t@@ -576,7 +600,7 @@ void SetupUninstall() { | |
RegSetValueEx(key,"InstallDirectory",0,REG_SZ,str->text,str->length); | |
RegCloseKey(key); | |
} else { | |
- DisplayError("Cannot create registry key: ",TRUE,FALSE); | |
+ DisplayError("Cannot create registry key for uninstall",TRUE,FALSE); | |
} | |
bstr_assign_windir(str); | |
t@@ -587,11 +611,11 @@ void SetupUninstall() { | |
bstr_appendpath(uninstexe,"uninstall.exe"); | |
if (!MoveFile(uninstexe->text,str->text)) { | |
- DisplayError("Unable to create uninstall program: ",TRUE,FALSE); | |
+ DisplayError("Unable to create uninstall program",TRUE,FALSE); | |
} | |
DeleteFile(uninstexe->text); | |
- startmenu = GetStartMenuDir(idata); | |
+ startmenu = GetStartMenuDir(install_all_users, idata); | |
bstr_assign(link,startmenu); | |
bstr_appendpath(link,"Uninstall "); | |
bstr_append(link,idata->product); | |
t@@ -636,7 +660,7 @@ void StartRemoveOldVersion(char *oldversion,InstData *idat… | |
DeleteFileList(old->instfiles,hwnd,idata->keepfiles); | |
DeleteFileList(old->extrafiles,hwnd,idata->keepfiles); | |
- startmenu = GetStartMenuDir(old); | |
+ startmenu = GetStartMenuDir(old->flags & IF_ALLUSERS, old); | |
desktop = GetDesktopDir(); | |
DeleteLinkList(startmenu,old->startmenu,hwnd); | |
DeleteLinkList(desktop,old->desktop,hwnd); | |
t@@ -682,7 +706,7 @@ void FinishRemoveOldVersion(char *oldversion,InstData *ida… | |
if (strcmp(idata->startmenudir,oldidata->startmenudir)!=0) { | |
SetCurrentDirectory(desktop); /* Make sure we're not in the menu dir */ | |
- startmenu = GetStartMenuDir(oldidata); | |
+ startmenu = GetStartMenuDir(oldidata->flags & IF_ALLUSERS, oldidata); | |
if (!RemoveWholeDirectory(startmenu)) { | |
bstr_assign(str,"Could not remove old Start Menu directory:\n"); | |
bstr_append(str,startmenu); | |
t@@ -707,7 +731,7 @@ void FinishRemoveOldVersion(char *oldversion,InstData *ida… | |
DWORD WINAPI DoInstall(LPVOID lpParam) { | |
HANDLE fout,logf,fin; | |
DWORD bytes_written,fileleft; | |
- BOOL skipfile; | |
+ BOOL skipfile, service_installed; | |
char *inbuf,*outbuf; | |
int status,count; | |
z_stream z; | |
t@@ -807,14 +831,34 @@ DWORD WINAPI DoInstall(LPVOID lpParam) { | |
FinishRemoveOldVersion(oldversion,idata,oldidata); | |
- InstallService(idata); | |
+ if (services_supported) { | |
+ service_installed = InstallService(idata); | |
+ } else { | |
+ service_installed = FALSE; | |
+ } | |
+ | |
+ if (service_installed) { | |
+ MessageBox(mainDlg[CurrentDialog], | |
+ "The dopewars server has been installed as an NT Service, " | |
+ "and configured\nfor manual startup. To start or stop this " | |
+ "service, or to configure it to run\nautomatically when " | |
+ "you turn on your computer, see the \"Services\" application\n" | |
+ "from Control Panel. You can also run an interactive server " | |
+ "by using\nthe \"dopewars server\" shortcut from the desktop " | |
+ "and/or Start Menu.","Service Installed",MB_OK); | |
+ } | |
CoInitialize(NULL); | |
SetupShortcuts(logf); | |
SetupUninstall(); | |
CoUninitialize(); | |
- WriteServiceDetails(logf,idata->service); | |
+ WriteServiceDetails(logf,service_installed ? idata->service : NULL); | |
+ | |
+ if (install_all_users) { | |
+ idata->flags |= IF_ALLUSERS; | |
+ } | |
+ WriteInstFlags(logf, idata->flags); | |
CloseHandle(logf); | |
t@@ -836,9 +880,11 @@ void FillFolderList(void) { | |
folderlist = GetDlgItem(mainDlg[DL_SHORTCUTS],LB_FOLDLIST); | |
if (!folderlist) return; | |
+ SendMessage(folderlist,LB_RESETCONTENT,0,0); | |
+ | |
str=bstr_new(); | |
- startdir=GetStartMenuTopDir(); | |
+ startdir=GetStartMenuTopDir(install_all_users); | |
bstr_assign(str,startdir); | |
bfree(startdir); | |
bstr_appendpath(str,"Programs\\*"); | |
t@@ -858,6 +904,17 @@ void FillFolderList(void) { | |
bstr_free(str,TRUE); | |
} | |
+BOOL CheckAdminRights(void) { | |
+ return (!services_supported || have_admin_rights || | |
+ MessageBox(NULL, | |
+ "To successfully install all components of this " | |
+ "program Administrator\nrights are required, and you " | |
+ "do not appear to have them. Do you want\nto attempt " | |
+ "to continue the installation anyway?", | |
+ "Administrator rights not found", | |
+ MB_YESNO | MB_DEFBUTTON2)==IDYES); | |
+} | |
+ | |
BOOL CheckExistingInstall(InstData *idata) { | |
bstr *str; | |
char *sep,*prodname,*prodversion; | |
t@@ -924,6 +981,22 @@ BOOL CheckExistingInstall(InstData *idata) { | |
return retval; | |
} | |
+BOOL SetDefaultInstall(void) { | |
+ HWND dlg; | |
+ | |
+ dlg = mainDlg[DL_INTRO]; | |
+ | |
+ if (services_supported) { | |
+ CheckRadioButton(dlg, RB_ALLUSERS, RB_ONEUSER, | |
+ have_admin_rights ? RB_ALLUSERS : RB_ONEUSER); | |
+ } else { | |
+ ShowWindow(GetDlgItem(dlg, RB_ALLUSERS), SW_HIDE); | |
+ ShowWindow(GetDlgItem(dlg, RB_ONEUSER), SW_HIDE); | |
+ } | |
+ | |
+ return have_admin_rights; | |
+} | |
+ | |
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, | |
LPSTR lpszCmdParam,int nCmdShow) { | |
MSG msg; | |
t@@ -941,11 +1014,13 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPre… | |
mainDlg[i] = CreateDialog(hInst,MAKEINTRESOURCE(i+1),NULL,MainDlgProc); | |
} | |
+ ServiceCheck(&services_supported,&have_admin_rights); | |
+ | |
+ install_all_users = SetDefaultInstall(); | |
+ | |
CheckDlgButton(mainDlg[DL_SHORTCUTS],CB_DESKTOP,BST_CHECKED); | |
EnableWindow(GetDlgItem(mainDlg[DL_DOINSTALL],BT_FINISH),FALSE); | |
- FillFolderList(); | |
- | |
ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_COMPLETE),SW_HIDE); | |
ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_EXIT),SW_HIDE); | |
t@@ -966,7 +1041,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevI… | |
for (i=0;i<DL_NUM;i++) SetGuiFont(mainDlg[i]); | |
- if (CheckExistingInstall(idata)) { | |
+ if (CheckAdminRights() && CheckExistingInstall(idata)) { | |
CurrentDialog=DL_NUM; | |
ShowNewDialog(DL_INTRO); | |
diff --git a/win32/uninstall.c b/win32/uninstall.c | |
t@@ -70,7 +70,7 @@ DWORD WINAPI DoUninstall(LPVOID lpParam) { | |
DeleteFileList(idata->instfiles,delstat,NULL); | |
DeleteFileList(idata->extrafiles,delstat,NULL); | |
- startmenu = GetStartMenuDir(idata); | |
+ startmenu = GetStartMenuDir(idata->flags & IF_ALLUSERS, idata); | |
desktop = GetDesktopDir(); | |
DeleteLinkList(startmenu,idata->startmenu,delstat); | |
DeleteLinkList(desktop,idata->desktop,delstat); | |
diff --git a/win32/util.c b/win32/util.c | |
t@@ -323,6 +323,16 @@ void FreeInstData(InstData *idata,BOOL freepts) { | |
bfree(idata); | |
} | |
+void WriteInstFlags(HANDLE fout, InstFlags flags) { | |
+ DWORD bytes_written; | |
+ char str[3]; | |
+ | |
+ str[0] = (char)flags; | |
+ if (!WriteFile(fout,str,1,&bytes_written,NULL)) { | |
+ printf("Write error\n"); | |
+ } | |
+} | |
+ | |
void WriteServiceDetails(HANDLE fout,NTService *service) { | |
DWORD bytes_written; | |
char str[]=""; | |
t@@ -412,19 +422,19 @@ static char *GetSpecialDir(int dirtype) { | |
return (doneOK ? bstrdup(szDir) : NULL); | |
} | |
-char *GetStartMenuTopDir(void) { | |
- return GetSpecialDir(CSIDL_STARTMENU); | |
+char *GetStartMenuTopDir(BOOL AllUsers) { | |
+ return GetSpecialDir(AllUsers ? CSIDL_COMMON_STARTMENU : CSIDL_STARTMENU); | |
} | |
char *GetDesktopDir(void) { | |
return GetSpecialDir(CSIDL_DESKTOPDIRECTORY); | |
} | |
-char *GetStartMenuDir(InstData *idata) { | |
+char *GetStartMenuDir(BOOL AllUsers, InstData *idata) { | |
bstr *str; | |
char *topdir,*retval; | |
- topdir=GetStartMenuTopDir(); | |
+ topdir=GetStartMenuTopDir(AllUsers); | |
str = bstr_new(); | |
t@@ -563,6 +573,18 @@ InstLink *ReadLinkList(HANDLE fin) { | |
return first; | |
} | |
+InstFlags ReadInstFlags(HANDLE fin) { | |
+ DWORD bytes_read; | |
+ char buf[3]; | |
+ | |
+ buf[0] = 0; | |
+ if (!ReadFile(fin,buf,1,&bytes_read,NULL)) { | |
+ printf("Read error\n"); | |
+ } | |
+ | |
+ return (InstFlags)buf[0]; | |
+} | |
+ | |
NTService *ReadServiceDetails(HANDLE fin) { | |
NTService *service=NULL; | |
char *name,*disp,*desc,*exe; | |
t@@ -645,12 +667,14 @@ InstData *ReadOldInstData(HANDLE fin,char *product,char … | |
idata->instfiles = ReadFileList(fin); | |
idata->extrafiles = ReadFileList(fin); | |
+ idata->keepfiles = NULL; | |
idata->startmenu = ReadLinkList(fin); | |
idata->desktop = ReadLinkList(fin); | |
idata->service = ReadServiceDetails(fin); | |
- idata->keepfiles = ReadFileList(fin); | |
+ | |
+ idata->flags = ReadInstFlags(fin); | |
return idata; | |
} | |
diff --git a/win32/util.h b/win32/util.h | |
t@@ -46,6 +46,10 @@ typedef struct _NTService { | |
char *exe; | |
} NTService; | |
+typedef enum { | |
+ IF_ALLUSERS = 1 | |
+} InstFlags; | |
+ | |
typedef struct _InstData { | |
char *product; | |
char *installdir,*startmenudir; | |
t@@ -56,6 +60,7 @@ typedef struct _InstData { | |
InstFiles *keepfiles; | |
InstLink *startmenu; | |
InstLink *desktop; | |
+ InstFlags flags; | |
} InstData; | |
extern const char *UninstallKey; | |
t@@ -93,10 +98,11 @@ void AddServiceDetails(char *servicename,char *servicedisp, | |
NTService **service); | |
void FreeServiceDetails(NTService *service,BOOL freepts); | |
void WriteServiceDetails(HANDLE fout,NTService *service); | |
+void WriteInstFlags(HANDLE fout, InstFlags flags); | |
void WriteLinkList(HANDLE fout,InstLink *listpt); | |
void WriteFileList(HANDLE fout,InstFiles *listpt); | |
-char *GetStartMenuTopDir(void); | |
-char *GetStartMenuDir(InstData *idata); | |
+char *GetStartMenuTopDir(BOOL AllUsers); | |
+char *GetStartMenuDir(BOOL AllUsers, InstData *idata); | |
char *GetDesktopDir(void); | |
BOOL CreateWholeDirectory(char *path); | |
BOOL RemoveWholeDirectory(char *path); |