-rw-r--r-- | shared-code/install.h | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/shared-code/install.h b/shared-code/install.h new file mode 100644 index 0000000..8c55ca9 --- a/dev/null +++ b/shared-code/install.h | |||
@@ -0,0 +1,370 @@ | |||
1 | #defineWIN32_LEAN_AND_MEAN | ||
2 | #define VC_EXTRALEAN | ||
3 | #define WIN32_EXTRALEAN | ||
4 | #include <windows.h> | ||
5 | #include <shlobj.h> | ||
6 | #include <winver.h> | ||
7 | #include <crtdbg.h> | ||
8 | #include <string.h> | ||
9 | #include <stdio.h> | ||
10 | |||
11 | extern "C" WINSHELLAPI void WINAPI SHFree( LPVOID); | ||
12 | |||
13 | template<class T> class Smart{ | ||
14 | public: | ||
15 | T *pT; | ||
16 | |||
17 | Smart() : pT(NULL) {} | ||
18 | Smart(int cb) : pT(new T[cb]) {} | ||
19 | Smart(T* p) : pT(p) {} | ||
20 | ~Smart() { if(pT)delete pT; } | ||
21 | |||
22 | Smart& operator=(T* p) { if(pT)delete pT; pT=p; return *this; } | ||
23 | operator T* () { return pT; } | ||
24 | |||
25 | //T& operator[](int ndx) { return pT[ndx]; } | ||
26 | |||
27 | T* Detach() { T* rv = pT; pT=NULL; return rv; } | ||
28 | }; | ||
29 | typedefSmart<char> STRING; | ||
30 | |||
31 | #define APPEND_SLASH(str) if((str)[strlen(str)-1]!='\\')strcat(str,"\\") | ||
32 | |||
33 | HINSTANCE theInstance; | ||
34 | |||
35 | LPSTR strFETCH_REG_KEY(HKEY hRoot,LPCSTR subKey,LPCSTR val) | ||
36 | { | ||
37 | HKEY hkey; | ||
38 | if(RegOpenKeyEx(hRoot,subKey,0,KEY_QUERY_VALUE,&hkey)!=ERROR_SUCCESS) | ||
39 | return NULL; | ||
40 | DWORD kType,cb=0; | ||
41 | STRING rv; | ||
42 | if(RegQueryValueEx(hkey,val,NULL,&kType,NULL,&cb)==ERROR_SUCCESS && kType==REG_SZ){ | ||
43 | rv= new char[cb]; | ||
44 | _ASSERT(rv!=NULL); | ||
45 | if(RegQueryValueEx(hkey,val,NULL,&kType,(LPBYTE)(LPSTR)rv,&cb)!=ERROR_SUCCESS) | ||
46 | rv=NULL; | ||
47 | } | ||
48 | RegCloseKey(hkey); | ||
49 | return rv.Detach(); | ||
50 | } | ||
51 | |||
52 | BOOL strSET_REG_KEY(HKEY hRoot,LPCSTR subKey,LPCSTR valName,LPCSTR val) | ||
53 | { | ||
54 | HKEY hkey; | ||
55 | DWORD dw; | ||
56 | if(RegCreateKeyEx(hRoot,subKey,0,REG_NONE,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,NULL,&hkey,&dw)!=ERROR_SUCCESS) | ||
57 | return FALSE; | ||
58 | BOOL rv = (RegSetValueEx(hkey,valName,0,REG_SZ,(LPBYTE)val,strlen(val)+1)==ERROR_SUCCESS); | ||
59 | RegCloseKey(hkey); | ||
60 | return rv; | ||
61 | } | ||
62 | |||
63 | void MAKE_PATH(LPCSTR path) | ||
64 | { | ||
65 | STRING tmp(strlen(path)+1); | ||
66 | LPCSTR t0=path; | ||
67 | LPSTR t1=tmp; | ||
68 | while(*t0){ | ||
69 | if((*t0)=='\\'){ | ||
70 | *t1=0; | ||
71 | CreateDirectory(tmp,NULL); | ||
72 | } | ||
73 | *(t1++)=*(t0++); | ||
74 | } | ||
75 | *t1=0; | ||
76 | CreateDirectory(tmp,NULL); | ||
77 | } | ||
78 | |||
79 | BOOL ADDMENU(LPCSTR menu,LPCSTR item,LPCSTR path,LPCSTR program) | ||
80 | { | ||
81 | STRING stm = strFETCH_REG_KEY(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders","Programs"); | ||
82 | if(!stm) | ||
83 | return FALSE; | ||
84 | int pil = 1+strlen(path)+1+strlen(program)+1+1; | ||
85 | STRING pi(pil); | ||
86 | strcpy(pi,path); | ||
87 | APPEND_SLASH(pi); | ||
88 | strcat(pi,program); | ||
89 | int ipl = strlen(stm)+1+strlen(menu)+1+strlen(item)+4+1; | ||
90 | STRING ip(ipl); | ||
91 | memmove(ip,stm,strlen(stm)+1); | ||
92 | APPEND_SLASH(ip); | ||
93 | strcat(ip,menu); | ||
94 | MAKE_PATH(ip); | ||
95 | APPEND_SLASH(ip); | ||
96 | strcat(ip,item); | ||
97 | strcat(ip,".lnk"); | ||
98 | IShellLink* sl = NULL; | ||
99 | IPersistFile* pf = NULL; | ||
100 | BOOL rv = FALSE; | ||
101 | do{ | ||
102 | HRESULT hrv = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID*)&sl); | ||
103 | if(!SUCCEEDED(hrv)) | ||
104 | break; | ||
105 | sl->SetDescription(item); | ||
106 | sl->SetPath(pi); | ||
107 | hrv = sl->QueryInterface(IID_IPersistFile,(LPVOID*)&pf); | ||
108 | if(!SUCCEEDED(hrv)) | ||
109 | break; | ||
110 | WORD wsz[MAX_PATH]; | ||
111 | MultiByteToWideChar(CP_ACP,0,ip,-1,wsz,MAX_PATH); | ||
112 | hrv = pf->Save(wsz,TRUE); | ||
113 | if(SUCCEEDED(hrv)) | ||
114 | rv=TRUE; | ||
115 | }while(FALSE); | ||
116 | if(pf) | ||
117 | pf->Release(); | ||
118 | if(sl) | ||
119 | sl->Release(); | ||
120 | return rv; | ||
121 | } | ||
122 | |||
123 | FILE* CREATE_INF_FILE(LPCSTR path,LPCSTR file) | ||
124 | { | ||
125 | STRING fn(strlen(path)+1+strlen(file)+1); | ||
126 | strcpy(fn,path); | ||
127 | APPEND_SLASH(fn); | ||
128 | strcat(fn,file); | ||
129 | return fopen(fn,"wt"); | ||
130 | } | ||
131 | |||
132 | BOOL INSTALLFILE(LPCSTR res,LPCSTR path,LPCSTR file) | ||
133 | { | ||
134 | STRING temp(MAX_PATH); | ||
135 | if(!GetTempPath(MAX_PATH,temp)) return FALSE; | ||
136 | STRING tf(MAX_PATH); | ||
137 | if(!GetTempFileName(temp,"KGI",0,tf)) return FALSE; | ||
138 | HRSRC hrsrc = FindResource(NULL,res,MAKEINTRESOURCE(RT_RCDATA)); | ||
139 | if(!hrsrc) return FALSE; | ||
140 | DWORD sor = SizeofResource(NULL,hrsrc); | ||
141 | if(!sor) return FALSE; | ||
142 | HGLOBAL hglobal = LoadResource(NULL,hrsrc); | ||
143 | if(!hglobal) return FALSE; | ||
144 | LPVOID lpv = LockResource(hglobal); | ||
145 | if(!lpv) return FALSE; | ||
146 | HANDLE hf = CreateFile(tf,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY,NULL); | ||
147 | if(!hf) return FALSE; | ||
148 | DWORD written = 0; | ||
149 | if(!WriteFile(hf,lpv,sor,&written,NULL) || written!=sor){ | ||
150 | CloseHandle(hf); | ||
151 | return FALSE; | ||
152 | } | ||
153 | CloseHandle(hf); | ||
154 | STRING toKill(strlen(tf)+1); | ||
155 | strcpy(toKill,tf); | ||
156 | for(int tmp=strlen(tf)-1;tmp>0 && ((tf[tmp])!='\\');tmp--); | ||
157 | if(tf[tmp]=='\\') | ||
158 | tf[tmp++]=0; | ||
159 | STRING nothing(_MAX_PATH); | ||
160 | UINT nothingLength=_MAX_PATH; | ||
161 | if(VerInstallFile(0,&tf[tmp],(LPSTR)file,tf,(LPSTR)path,NULL,nothing,¬hingLength)){ | ||
162 | DeleteFile(toKill); | ||
163 | return FALSE; | ||
164 | } | ||
165 | DeleteFile(toKill); | ||
166 | return TRUE; | ||
167 | } | ||
168 | |||
169 | LPCSTR pdTitle, pdPrompt; | ||
170 | char pdPath[_MAX_PATH]; | ||
171 | BOOL CALLBACK pathDlgProc(HWND hwnd,UINT uMsg,WPARAM wP,LPARAM lP) | ||
172 | { | ||
173 | switch(uMsg){ | ||
174 | case WM_INITDIALOG: | ||
175 | SetWindowText(hwnd,pdTitle); | ||
176 | SetDlgItemText(hwnd,IDC_PROMPT,pdPrompt); | ||
177 | SetDlgItemText(hwnd,IDC_PATH,pdPath); | ||
178 | SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); | ||
179 | return 1; | ||
180 | case WM_COMMAND: | ||
181 | switch(LOWORD(wP)){ // ID | ||
182 | case IDC_BROWSE: | ||
183 | switch(HIWORD(wP)){ | ||
184 | case BN_CLICKED: | ||
185 | { | ||
186 | BROWSEINFO bi; | ||
187 | memset(&bi,0,sizeof(bi)); | ||
188 | bi.hwndOwner=hwnd; | ||
189 | bi.pszDisplayName=pdPath; | ||
190 | bi.lpszTitle="Select Folder.."; | ||
191 | bi.ulFlags=BIF_RETURNONLYFSDIRS; | ||
192 | LPITEMIDLIST lpidl=SHBrowseForFolder(&bi); | ||
193 | if(lpidl){ | ||
194 | SHGetPathFromIDList(lpidl,pdPath); | ||
195 | SHFree(lpidl); | ||
196 | SetDlgItemText(hwnd,IDC_PATH,pdPath); | ||
197 | } | ||
198 | } | ||
199 | return 1; | ||
200 | } | ||
201 | break; | ||
202 | case IDOK: | ||
203 | switch(HIWORD(wP)){ | ||
204 | case BN_CLICKED: | ||
205 | if(GetDlgItemText(hwnd,IDC_PATH,pdPath,sizeof(pdPath))) | ||
206 | EndDialog(hwnd,IDOK); | ||
207 | else | ||
208 | // *** Error message | ||
209 | EndDialog(hwnd,IDCANCEL); | ||
210 | return 1; | ||
211 | } | ||
212 | break; | ||
213 | case IDCANCEL: | ||
214 | switch(HIWORD(wP)){ | ||
215 | case BN_CLICKED: | ||
216 | EndDialog(hwnd,IDCANCEL); | ||
217 | return 1; | ||
218 | } | ||
219 | break; | ||
220 | }; | ||
221 | break; | ||
222 | } | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | LPSTR REQUESTPATH(LPCSTR title,LPCSTR prompt,LPCSTR defPath) | ||
227 | { | ||
228 | pdTitle=title;pdPrompt=prompt; | ||
229 | strcpy(pdPath,defPath); | ||
230 | if(DialogBox(NULL,MAKEINTRESOURCE(IDD_PATH),NULL/*Parent*/,(DLGPROC)&pathDlgProc)!=IDOK) | ||
231 | return NULL; | ||
232 | STRING rv(strlen(pdPath)+1); | ||
233 | strcpy(rv,pdPath); | ||
234 | return rv.Detach(); | ||
235 | } | ||
236 | |||
237 | HKEY uninstallKey(LPCSTR regKey) { | ||
238 | STRING rk(100+strlen(regKey)+1); | ||
239 | sprintf(rk,"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s",regKey); | ||
240 | HKEY rv = NULL; | ||
241 | DWORD dw; | ||
242 | if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,rk,0,REG_NONE,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,NULL,&rv,&dw)!=ERROR_SUCCESS) | ||
243 | return NULL; | ||
244 | return rv; | ||
245 | } | ||
246 | |||
247 | BOOL REG_UNINSTALL_COMMAND(LPCSTR regKey,LPCSTR dName,LPCSTR iPath,LPCSTR iFile,LPCSTR iSection) | ||
248 | { | ||
249 | HKEY hKey = uninstallKey(regKey); | ||
250 | if(!hKey) | ||
251 | return FALSE; | ||
252 | BOOL rv=FALSE; | ||
253 | do{ | ||
254 | if(RegSetValueEx(hKey,"DisplayName",0,REG_SZ,(LPBYTE)dName,strlen(dName)+1)!=ERROR_SUCCESS) | ||
255 | break; | ||
256 | STRING us(50+strlen(iPath)+1+strlen(iFile)+strlen(iSection)+1); | ||
257 | strcpy(us,"RunDll32 setupapi.dll,InstallHinfSection "); | ||
258 | strcat(us,iSection); | ||
259 | strcat(us," 132 "); | ||
260 | strcat(us,iPath); | ||
261 | APPEND_SLASH(us); | ||
262 | strcat(us,iFile); | ||
263 | if(RegSetValueEx(hKey,"UninstallString",0,REG_SZ,(LPBYTE)(LPCSTR)us,strlen(us)+1)!=ERROR_SUCCESS) | ||
264 | break; | ||
265 | rv=TRUE; | ||
266 | }while(FALSE); | ||
267 | RegCloseKey(hKey); | ||
268 | return rv; | ||
269 | } | ||
270 | BOOL REG_UNINSTALL_ICON(LPCSTR regKey,LPCSTR path,LPCSTR file,int n) { | ||
271 | HKEY hKey = uninstallKey(regKey); | ||
272 | if(!hKey) | ||
273 | return FALSE; | ||
274 | STRING uis(strlen(path)+1+strlen(file)+7); | ||
275 | strcpy(uis,path); | ||
276 | APPEND_SLASH(uis); | ||
277 | strcat(uis,file); | ||
278 | char tmp[8]; | ||
279 | sprintf(tmp,";%d",n); | ||
280 | strcat(uis,tmp); | ||
281 | BOOL rv = TRUE; | ||
282 | if(RegSetValueEx(hKey,"DisplayIcon",0,REG_SZ,(LPBYTE)(LPCSTR)uis,strlen(uis)+1)!=ERROR_SUCCESS) | ||
283 | rv = FALSE; | ||
284 | RegCloseKey(hKey); | ||
285 | return rv; | ||
286 | } | ||
287 | BOOL REG_UNINSTALL_COMMENT(LPCSTR regKey,LPCSTR comment) { | ||
288 | HKEY hKey = uninstallKey(regKey); | ||
289 | if(!hKey) | ||
290 | return FALSE; | ||
291 | BOOL rv = TRUE; | ||
292 | if(RegSetValueEx(hKey,"lComment",0,REG_SZ,(LPBYTE)comment,strlen(comment)+1)!=ERROR_SUCCESS) | ||
293 | rv = FALSE; | ||
294 | RegCloseKey(hKey); | ||
295 | return rv; | ||
296 | } | ||
297 | BOOL REG_UNINSTALL_VERSION(LPCSTR regKey,LPCSTR version) { | ||
298 | HKEY hKey = uninstallKey(regKey); | ||
299 | if(!hKey) | ||
300 | return FALSE; | ||
301 | BOOL rv = TRUE; | ||
302 | if(RegSetValueEx(hKey,"DisplayVersion",0,REG_SZ,(LPBYTE)version,strlen(version)+1)!=ERROR_SUCCESS) | ||
303 | rv = FALSE; | ||
304 | RegCloseKey(hKey); | ||
305 | return rv; | ||
306 | } | ||
307 | BOOL REG_UNINSTALL_LOCATION(LPCSTR regKey,LPCSTR location) { | ||
308 | HKEY hKey = uninstallKey(regKey); | ||
309 | if(!hKey) | ||
310 | return FALSE; | ||
311 | BOOL rv = TRUE; | ||
312 | if(RegSetValueEx(hKey,"InstallLocation",0,REG_SZ,(LPBYTE)location,strlen(location)+1)!=ERROR_SUCCESS) | ||
313 | rv = FALSE; | ||
314 | RegCloseKey(hKey); | ||
315 | return rv; | ||
316 | } | ||
317 | BOOL REG_UNINSTALL_PUBLISHER(LPCSTR regKey,LPCSTR publisher) { | ||
318 | HKEY hKey = uninstallKey(regKey); | ||
319 | if(!hKey) | ||
320 | return FALSE; | ||
321 | BOOL rv = TRUE; | ||
322 | if(RegSetValueEx(hKey,"Publisher",0,REG_SZ,(LPBYTE)publisher,strlen(publisher)+1)!=ERROR_SUCCESS) | ||
323 | rv = FALSE; | ||
324 | RegCloseKey(hKey); | ||
325 | return rv; | ||
326 | } | ||
327 | BOOL REG_UNINSTALL_URLS(LPCSTR regKey,LPCSTR about,LPCSTR update) { | ||
328 | HKEY hKey = uninstallKey(regKey); | ||
329 | if(!hKey) | ||
330 | return FALSE; | ||
331 | BOOL rv = TRUE; | ||
332 | if(RegSetValueEx(hKey,"URLInfoAbout",0,REG_SZ,(LPBYTE)about,strlen(about)+1)!=ERROR_SUCCESS) | ||
333 | rv = FALSE; | ||
334 | if(RegSetValueEx(hKey,"URLUpdateInfo",0,REG_SZ,(LPBYTE)update,strlen(update)+1)!=ERROR_SUCCESS) | ||
335 | rv = FALSE; | ||
336 | RegCloseKey(hKey); | ||
337 | return rv; | ||
338 | } | ||
339 | |||
340 | #defineINF_FILE_HEADER(i) fprintf(i,"[Version]\nSignature=\"$CHICAGO$\"\n\n") | ||
341 | #define INF_FILE_SECTION(i,s) fprintf(i,"\n[%s]\n",s) | ||
342 | #defineINF_UNINSTALL_REG(i,p) fprintf(i,"HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s\nHKLM,Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s,DisplayName\nHKLM,Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s,UninstallString\n",p,p,p) | ||
343 | #define INF_MENU_GROUP(i,n,m) fprintf(i,"setup.ini, progman.groups,,\"group%d=%s\"\n",n,m) | ||
344 | #define INF_MENU_ITEM(i,n,m) fprintf(i,"setup.ini, group%d,, \"\"\"%s\"\"\"\n",n,m); | ||
345 | #define INF_REMOVE_ROOT(i,g,r) fprintf(i,"HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\DeleteFiles\\%s,,,\"%s\"\n",g,r) | ||
346 | #define INF_REMOVE_FILE(i,g,f) fprintf(i,"HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\DeleteFiles\\%s,%s,,\"%s\"\n",g,f,f) | ||
347 | #define INF_REMOVE_HELP_FILE(i,g,f) {INF_REMOVE_FILE(i,g,f".hlp");INF_REMOVE_FILE(i,g,f".cnt");INF_REMOVE_FILE(i,g,f".GID");INF_REMOVE_FILE(i,g,f".FTS");} | ||
348 | |||
349 | LPSTR GET_SHORT_PATH(LPCSTR path) | ||
350 | { | ||
351 | char tmp; | ||
352 | DWORD len = GetShortPathName(path,&tmp,1); | ||
353 | if(!len) | ||
354 | return NULL; | ||
355 | STRING rv(len+1); | ||
356 | if(!GetShortPathName(path,rv,len+1)) | ||
357 | return NULL; | ||
358 | return rv.Detach(); | ||
359 | } | ||
360 | |||
361 | BOOL Install(void); | ||
362 | |||
363 | int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int) | ||
364 | { | ||
365 | theInstance=hInstance; | ||
366 | CoInitialize(NULL); | ||
367 | Install(); | ||
368 | CoUninitialize(); | ||
369 | return 0; | ||
370 | } | ||