PageRenderTime 36ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/nsis-2.46-src/Source/exehead/Main.c

#
C | 351 lines | 241 code | 54 blank | 56 comment | 53 complexity | 2ec5b34550cf787a86c61f9f337478f8 MD5 | raw file
Possible License(s): CPL-1.0
  1. /*
  2. * main.c: executable header main code
  3. *
  4. * This file is a part of NSIS.
  5. *
  6. * Copyright (C) 1999-2009 Nullsoft and Contributors
  7. *
  8. * Licensed under the zlib/libpng license (the "License");
  9. * you may not use this file except in compliance with the License.
  10. *
  11. * Licence details can be found in the file COPYING.
  12. *
  13. * This software is provided 'as-is', without any express or implied
  14. * warranty.
  15. */
  16. #include "../Platform.h"
  17. #include <shlobj.h>
  18. #include <shellapi.h>
  19. #include "resource.h"
  20. #include "util.h"
  21. #include "fileform.h"
  22. #include "state.h"
  23. #include "ui.h"
  24. #include "lang.h"
  25. #include "state.h"
  26. #include "exec.h"
  27. #include "plugin.h"
  28. #if !defined(NSIS_CONFIG_VISIBLE_SUPPORT) && !defined(NSIS_CONFIG_SILENT_SUPPORT)
  29. #error One of NSIS_CONFIG_SILENT_SUPPORT or NSIS_CONFIG_VISIBLE_SUPPORT must be defined.
  30. #endif
  31. #ifdef NSIS_COMPRESS_WHOLE
  32. extern HANDLE dbd_hFile;
  33. #endif
  34. char g_caption[NSIS_MAX_STRLEN*2];
  35. #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
  36. HWND g_hwnd;
  37. HANDLE g_hInstance;
  38. #endif
  39. void NSISCALL CleanUp();
  40. char *ValidateTempDir()
  41. {
  42. validate_filename(state_temp_dir);
  43. if (!validpathspec(state_temp_dir))
  44. return NULL;
  45. addtrailingslash(state_temp_dir);
  46. CreateDirectory(state_temp_dir, NULL);
  47. // state_language is used as a temp var here
  48. return my_GetTempFileName(state_language, state_temp_dir);
  49. }
  50. void *g_SHGetFolderPath;
  51. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, int nCmdShow)
  52. {
  53. int ret = 0;
  54. const char *m_Err = _LANG_ERRORWRITINGTEMP;
  55. int cl_flags = 0;
  56. char *realcmds;
  57. char seekchar=' ';
  58. char *cmdline;
  59. InitCommonControls();
  60. SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  61. #if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
  62. {
  63. extern HRESULT g_hres;
  64. g_hres=OleInitialize(NULL);
  65. }
  66. #endif
  67. // load shfolder.dll before any script code is executed to avoid
  68. // weird situations where SetOutPath or even the extraction of
  69. // shfolder.dll will cause unexpected behavior.
  70. //
  71. // this also prevents the following:
  72. //
  73. // SetOutPath "C:\Program Files\NSIS" # maybe read from reg
  74. // File shfolder.dll
  75. // Delete $PROGRAMFILES\shfolder.dll # can't be deleted, as the
  76. // # new shfolder.dll is used
  77. // # to find its own path.
  78. g_SHGetFolderPath = myGetProcAddress(MGA_SHGetFolderPathA);
  79. {
  80. // workaround for bug #1008632
  81. // http://sourceforge.net/tracker/index.php?func=detail&aid=1008632&group_id=22049&atid=373085
  82. //
  83. // without this, SHGetSpecialFolderLocation doesn't always recognize
  84. // some special folders, like the desktop folder for all users, on
  85. // Windows 9x. unlike SHGetSpecialFolderPath, which is not available
  86. // on all versions of Windows, SHGetSpecialFolderLocation doesn't try
  87. // too hard to make sure the caller gets what he asked for. so we give
  88. // it a little push in the right direction by doing part of the work
  89. // for it.
  90. //
  91. // part of what SHGetFileInfo does, is to convert a path into an idl.
  92. // to do this conversion, it first needs to initialize the list of
  93. // special idls, which are exactly the idls we use to get the paths
  94. // of special folders (CSIDL_*).
  95. SHFILEINFO shfi;
  96. SHGetFileInfo("", 0, &shfi, sizeof(SHFILEINFO), 0);
  97. }
  98. mystrcpy(g_caption,_LANG_GENERIC_ERROR);
  99. mystrcpy(state_command_line, GetCommandLine());
  100. #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
  101. g_hInstance = GetModuleHandle(NULL);
  102. #endif//NSIS_CONFIG_VISIBLE_SUPPORT
  103. cmdline = state_command_line;
  104. if (*cmdline == '\"') seekchar = *cmdline++;
  105. cmdline=findchar(cmdline, seekchar);
  106. cmdline=CharNext(cmdline);
  107. realcmds=cmdline;
  108. while (*cmdline)
  109. {
  110. // skip over any spaces
  111. while (*cmdline == ' ') cmdline++;
  112. // get char we should look for to get the next parm
  113. seekchar = ' ';
  114. if (cmdline[0] == '\"')
  115. {
  116. cmdline++;
  117. seekchar = '\"';
  118. }
  119. // is it a switch?
  120. if (cmdline[0] == '/')
  121. {
  122. cmdline++;
  123. // this only works with spaces because they have just one bit on
  124. #define END_OF_ARG(c) (((c)|' ')==' ')
  125. #if defined(NSIS_CONFIG_VISIBLE_SUPPORT) && defined(NSIS_CONFIG_SILENT_SUPPORT)
  126. if (cmdline[0] == 'S' && END_OF_ARG(cmdline[1]))
  127. cl_flags |= FH_FLAGS_SILENT;
  128. #endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT
  129. #ifdef NSIS_CONFIG_CRC_SUPPORT
  130. if (*(LPDWORD)cmdline == CHAR4_TO_DWORD('N','C','R','C') && END_OF_ARG(cmdline[4]))
  131. cl_flags |= FH_FLAGS_NO_CRC;
  132. #endif//NSIS_CONFIG_CRC_SUPPORT
  133. if (*(LPDWORD)(cmdline-2) == CHAR4_TO_DWORD(' ', '/', 'D','='))
  134. {
  135. *(LPDWORD)(cmdline-2)=0; // keep this from being passed to uninstaller if necessary
  136. mystrcpy(state_install_directory,cmdline+2);
  137. break; // /D= must always be last
  138. }
  139. }
  140. // skip over our parm
  141. cmdline = findchar(cmdline, seekchar);
  142. // skip the quote
  143. if (*cmdline == '\"')
  144. cmdline++;
  145. }
  146. GetTempPath(NSIS_MAX_STRLEN, state_temp_dir);
  147. if (!ValidateTempDir())
  148. {
  149. GetWindowsDirectory(state_temp_dir, NSIS_MAX_STRLEN - 5); // leave space for \Temp
  150. mystrcat(state_temp_dir, "\\Temp");
  151. if (!ValidateTempDir())
  152. {
  153. goto end;
  154. }
  155. }
  156. DeleteFile(state_language);
  157. m_Err = loadHeaders(cl_flags);
  158. if (m_Err) goto end;
  159. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  160. if (g_is_uninstaller)
  161. {
  162. char *p = findchar(state_command_line, 0);
  163. // state_command_line has state_install_directory right after it in memory, so reading
  164. // a bit over state_command_line won't do any harm
  165. while (p >= state_command_line && *(LPDWORD)p != CHAR4_TO_DWORD(' ', '_', '?', '=')) p--;
  166. m_Err = _LANG_UNINSTINITERROR;
  167. if (p >= state_command_line)
  168. {
  169. *p=0; // terminate before "_?="
  170. p+=4; // skip over " _?="
  171. if (is_valid_instpath(p))
  172. {
  173. mystrcpy(state_install_directory, p);
  174. mystrcpy(state_output_directory, p);
  175. m_Err = 0;
  176. }
  177. else
  178. {
  179. goto end;
  180. }
  181. }
  182. else
  183. {
  184. int x;
  185. mystrcat(state_temp_dir,"~nsu.tmp");
  186. // check if already running from uninstaller temp dir
  187. // this prevents recursive uninstaller calls
  188. if (!lstrcmpi(state_temp_dir,state_exe_directory))
  189. goto end;
  190. CreateDirectory(state_temp_dir,NULL);
  191. SetCurrentDirectory(state_temp_dir);
  192. if (!state_install_directory[0])
  193. mystrcpy(state_install_directory,state_exe_directory);
  194. mystrcpy(g_usrvars[0], realcmds);
  195. *(LPWORD)g_usrvars[1] = CHAR2_TO_WORD('A',0);
  196. for (x = 0; x < 26; x ++)
  197. {
  198. static char buf2[NSIS_MAX_STRLEN];
  199. GetNSISString(buf2,g_header->str_uninstchild); // $TEMP\$1u_.exe
  200. DeleteFile(buf2); // clean up after all the other ones if they are there
  201. if (m_Err) // not done yet
  202. {
  203. // copy file
  204. if (CopyFile(state_exe_path,buf2,TRUE))
  205. {
  206. HANDLE hProc;
  207. #ifdef NSIS_SUPPORT_MOVEONREBOOT
  208. MoveFileOnReboot(buf2,NULL);
  209. #endif
  210. GetNSISString(buf2,g_header->str_uninstcmd); // '"$TEMP\$1u_.exe" $0 _?=$INSTDIR\'
  211. hProc=myCreateProcess(buf2);
  212. if (hProc)
  213. {
  214. CloseHandle(hProc);
  215. // success
  216. m_Err = 0;
  217. }
  218. }
  219. }
  220. g_usrvars[1][0]++;
  221. }
  222. #ifdef NSIS_SUPPORT_MOVEONREBOOT
  223. MoveFileOnReboot(state_temp_dir,NULL);
  224. #endif
  225. goto end;
  226. }
  227. }
  228. #endif//NSIS_CONFIG_UNINSTALL_SUPPORT
  229. g_exec_flags.errlvl = -1;
  230. ret = ui_doinstall();
  231. #ifdef NSIS_CONFIG_LOG
  232. #if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
  233. log_write(1);
  234. #endif//!NSIS_CONFIG_LOG_ODS && !NSIS_CONFIG_LOG_STDOUT
  235. #endif//NSIS_CONFIG_LOG
  236. end:
  237. CleanUp();
  238. #if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
  239. OleUninitialize();
  240. #endif
  241. if (m_Err)
  242. {
  243. my_MessageBox(m_Err, MB_OK | MB_ICONSTOP | (IDOK << 21));
  244. ExitProcess(2);
  245. return 0;
  246. }
  247. #ifdef NSIS_SUPPORT_REBOOT
  248. if (g_exec_flags.reboot_called)
  249. {
  250. BOOL (WINAPI *OPT)(HANDLE, DWORD,PHANDLE);
  251. BOOL (WINAPI *LPV)(LPCTSTR,LPCTSTR,PLUID);
  252. BOOL (WINAPI *ATP)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
  253. OPT=myGetProcAddress(MGA_OpenProcessToken);
  254. LPV=myGetProcAddress(MGA_LookupPrivilegeValueA);
  255. ATP=myGetProcAddress(MGA_AdjustTokenPrivileges);
  256. if (OPT && LPV && ATP)
  257. {
  258. HANDLE hToken;
  259. TOKEN_PRIVILEGES tkp;
  260. if (OPT(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  261. {
  262. LPV(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
  263. tkp.PrivilegeCount = 1;
  264. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  265. ATP(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
  266. }
  267. }
  268. if (!ExitWindowsEx(EWX_REBOOT,0))
  269. ExecuteCallbackFunction(CB_ONREBOOTFAILED);
  270. }
  271. #endif//NSIS_SUPPORT_REBOOT
  272. if (g_exec_flags.errlvl != -1)
  273. ret = g_exec_flags.errlvl;
  274. ExitProcess(ret);
  275. return 0;
  276. }
  277. void NSISCALL CleanUp()
  278. {
  279. if (g_db_hFile != INVALID_HANDLE_VALUE)
  280. {
  281. CloseHandle(g_db_hFile);
  282. g_db_hFile = INVALID_HANDLE_VALUE;
  283. }
  284. #ifdef NSIS_COMPRESS_WHOLE
  285. if (dbd_hFile != INVALID_HANDLE_VALUE)
  286. {
  287. CloseHandle(dbd_hFile);
  288. dbd_hFile = INVALID_HANDLE_VALUE;
  289. }
  290. #endif
  291. // Notify plugins that we are about to unload
  292. Plugins_UnloadAll();
  293. #ifdef NSIS_CONFIG_PLUGIN_SUPPORT
  294. // Clean up after plug-ins
  295. myDelete(state_plugins_dir, DEL_DIR | DEL_RECURSE | DEL_REBOOT);
  296. #endif // NSIS_CONFIG_PLUGIN_SUPPORT
  297. }