1 #include "CtrlLib.h"
2
3 namespace Upp {
4
5 #ifdef GUI_WIN
6 #ifndef PLATFORM_WINCE
7
8 #define LLOG(x)
9
10 static String s_updatedir;
11 static String s_updater;
12
UpdateSetDir(const char * path)13 void UpdateSetDir(const char *path)
14 {
15 s_updatedir = path;
16 }
17
UpdateSetUpdater(const char * exename)18 void UpdateSetUpdater(const char *exename)
19 {
20 s_updater = exename;
21 }
22
UpdateGetDir()23 String UpdateGetDir()
24 {
25 return Nvl(s_updatedir, GetIniKey("UPDATE"));
26 }
27
FileTimeToTime(const FILETIME & time)28 Time FileTimeToTime(const FILETIME& time) {
29 SYSTEMTIME t;
30 FileTimeToSystemTime(&time, &t);
31 return Time(t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
32 }
33
NoUpdate(const char * dsf,const char * srf,int & len)34 bool NoUpdate(const char *dsf, const char *srf, int& len) {
35 FindFile dst(dsf);
36 FindFile src(srf);
37 if(!src) return true;
38 len = (int)src.GetLength();
39 if(!dst) return false;
40 return abs(FileTimeToTime(dst.GetLastWriteTime()) - FileTimeToTime(src.GetLastWriteTime()))
41 < 100 && len == dst.GetLength();
42 }
43
UpdateFile(String dst,String src)44 void UpdateFile(String dst, String src)
45 {
46 if(src.IsEmpty()) return;
47 String filename = GetFileName(dst);
48 int len;
49 if(NoUpdate(dst, src, len)) return;
50 String tmp = dst + ".tmp";
51 Progress pi;
52 pi.Title((t_("Updating ") + filename).ToWString());
53 pi.SetText(t_("Updating ") + filename);
54 // pi.Open();
55 FileIn in(src);
56 if(!in)
57 {
58 Exclamation(Format(t_("Error opening file [* \1%s\1]."), src));
59 return;
60 }
61 FileDelete(tmp);
62 FileOut out(tmp);
63 dword n = 0;
64 char buffer[2048];
65 if(!out)
66 {
67 Exclamation(Format(t_("Error creating file [* \1%s\1]."), tmp));
68 return;
69 }
70 for(;;)
71 {
72 dword i = in.Get(buffer, 2048);
73 if(i == 0) break;
74 out.Put(buffer, i);
75 n += i;
76 pi.Set(n, len);
77 if(pi.Canceled() && PromptYesNo(t_("Aborting update is likely to cause trouble when running the application for the next time.\nContinue?")))
78 {
79 out.Close();
80 FileDelete(tmp);
81 return;
82 }
83 }
84 out.SetTime(in.GetTime());
85 out.Close();
86 if(out.IsError())
87 {
88 Exclamation(Format(t_("Error writing file [* \1%s\1]."), tmp));
89 FileDelete(tmp);
90 return;
91 }
92 String old = dst + ".old";
93 pi.SetText(Format(t_("Overwriting %s"), dst));
94 pi.SetTotal(10000);
95 int start = msecs();
96 for(;;)
97 {
98 SetFileAttributes(dst, 0);
99 FileDelete(old);
100 FileMove(dst, old);
101 if(FileMove(tmp, dst))
102 return;
103 if(pi.SetPosCanceled(msecs(start) % 10000) && PromptYesNo(t_("Aborting update is likely to cause trouble when running the application for the next time.\nContinue?")))
104 return;
105 Sleep(500);
106 }
107 }
108
UpdateFile(const char * filename)109 void UpdateFile(const char *filename)
110 {
111 String dst = GetExeDirFile(filename);
112 String src = UpdateGetDir();
113 if(IsNull(src))
114 return;
115 UpdateFile(dst, AppendFileName(src, filename));
116 }
117
FixArg(String s)118 static String FixArg(String s)
119 {
120 if(s.Find(' ') < 0 && s.Find('\"') < 0)
121 return s;
122 String ucmd;
123 ucmd << '\"';
124 for(const char *p = s; *p; p++)
125 if(*p == '\"')
126 ucmd << "\"\"";
127 else
128 ucmd << *p;
129 ucmd << '\"';
130 return ucmd;
131 }
132
SelfUpdate()133 void SelfUpdate() {
134 char dst[512];
135 UpdateFile(Nvl(s_updater, String("UPDATER.EXE")));
136 ::GetModuleFileName(NULL, dst, 512);
137 {
138 String src = UpdateGetDir();
139 if(src.IsEmpty()) return;
140 src = AppendFileName(src, GetFileNamePos(dst));
141 int dummy;
142 if(NoUpdate(dst, src, dummy)) return;
143 String commandline;
144 const Vector<String>& cmd = CommandLine();
145 for(int i = 0; i < cmd.GetCount(); i++) {
146 commandline += ' ';
147 commandline += FixArg(cmd[i]);
148 }
149 if(WinExec(GetExeDirFile("updater.exe") + " " + GetFileName(dst) + commandline, SW_SHOWNORMAL) <= 31)
150 return;
151 }
152 exit(0);
153 }
154
SelfUpdateSelf()155 bool SelfUpdateSelf()
156 {
157 const Vector<String>& cmdline = CommandLine();
158 String exe = GetExeFilePath();
159
160 if(cmdline.GetCount() >= 2 && cmdline[0] == "-update")
161 { // updater
162 String exec = FixArg(cmdline[1]);
163 UpdateFile(exec, exe);
164 for(int i = 2; i < cmdline.GetCount(); i++)
165 exec << ' ' << FixArg(cmdline[i]);
166 WinExec(exec, SW_SHOWNORMAL);
167 return true;
168 }
169
170 String src = UpdateGetDir();
171 if(src.IsEmpty()) return false;
172 src = AppendFileName(src, GetFileNamePos(exe));
173 int dummy;
174 if(NoUpdate(exe, src, dummy)) return false;
175
176 String commandline;
177 commandline << src << " -update " << FixArg(exe);
178 for(int i = 0; i < cmdline.GetCount(); i++)
179 commandline << ' ' << FixArg(cmdline[i]);
180 LLOG("SelfUpdateSelf (running updater): " << commandline);
181 return WinExec(commandline, SW_SHOWNORMAL) >= 32;
182 }
183
184 #endif
185 #endif
186
187 }
188