Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

561 lines
16 KiB

  1. // ===========================================================================
  2. // File: HOOKS.CXX
  3. // implements CSetupHook
  4. //
  5. #include <cdlpch.h>
  6. #include "advpkp.h"
  7. #include "advpub.h"
  8. CRunSetupHook g_RunSetupHook;
  9. extern DWORD g_dwCodeDownloadSetupFlags;
  10. // ---------------------------------------------------------------------------
  11. // %%Function: CSetupHook::CSetupHook
  12. // ---------------------------------------------------------------------------
  13. CSetupHook::CSetupHook(
  14. CDownload *pdl,
  15. LPCSTR szHook,
  16. LPCSTR szInf,
  17. LPCSTR szInfSection,
  18. DWORD flags,
  19. HRESULT *phr)
  20. :
  21. m_pdl(pdl),
  22. m_flags(flags),
  23. m_state(INSTALL_INIT)
  24. {
  25. DEBUG_ENTER((DBG_DOWNLOAD,
  26. None,
  27. "CSetupHook::CSetupHook",
  28. "this=%#x, %.80q, %.80q, %.80q, %#x, %#x",
  29. this, pdl, szHook, szInf, szInfSection, flags, phr
  30. ));
  31. Assert(szInf);
  32. *phr = S_OK;
  33. if (szInf) {
  34. m_szInf= new char [lstrlen(szInf)+1];
  35. if (m_szInf)
  36. lstrcpy(m_szInf, szInf);
  37. else
  38. *phr = E_OUTOFMEMORY;
  39. } else {
  40. m_szInf = NULL;
  41. }
  42. if (szInfSection) {
  43. m_szInfSection = new char [lstrlen(szInfSection)+1];
  44. if (m_szInfSection)
  45. lstrcpy(m_szInfSection, szInfSection);
  46. else
  47. *phr = E_OUTOFMEMORY;
  48. } else {
  49. m_szInfSection = NULL;
  50. }
  51. if (szHook) {
  52. m_szHook = new char [lstrlen(szHook)+1];
  53. if (m_szHook)
  54. lstrcpy(m_szHook, szHook);
  55. else
  56. *phr = E_OUTOFMEMORY;
  57. } else {
  58. m_szHook = NULL;
  59. }
  60. DEBUG_LEAVE(0);
  61. } // CSetupHook
  62. // ---------------------------------------------------------------------------
  63. // %%Function: CSetupHook::~CSetupHook
  64. // ---------------------------------------------------------------------------
  65. CSetupHook::~CSetupHook()
  66. {
  67. DEBUG_ENTER((DBG_DOWNLOAD,
  68. None,
  69. "CSetupHook::~CSetupHook",
  70. "this=%#x",
  71. this
  72. ));
  73. if (m_szInf)
  74. SAFEDELETE(m_szInf);
  75. if (m_szInfSection)
  76. SAFEDELETE(m_szInfSection);
  77. if (m_szHook)
  78. SAFEDELETE(m_szHook);
  79. DEBUG_LEAVE(0);
  80. } // ~CSetupHook
  81. // ---------------------------------------------------------------------------
  82. // %%Function: CSetupHook::ExpandVar
  83. // ---------------------------------------------------------------------------
  84. HRESULT
  85. CSetupHook::ExpandVar(
  86. LPSTR& pchSrc, // passed by ref!
  87. LPSTR& pchOut, // passed by ref!
  88. DWORD& cbLen, // passed by ref!
  89. DWORD cbBuffer,
  90. const char * szVars[],
  91. const char * szValues[])
  92. {
  93. DEBUG_ENTER((DBG_DOWNLOAD,
  94. Hresult,
  95. "CSetupHook::ExpandVar",
  96. "%#x, %#x, %#x, %#x, %#x, %#x",
  97. &pchSrc, &pchOut, &cbLen, cbBuffer, szVars, szValues
  98. ));
  99. HRESULT hr = S_FALSE;
  100. int cbvar = 0;
  101. Assert (*pchSrc == '%');
  102. for (int i=0; szVars[i] && (cbvar = lstrlen(szVars[i])) ; i++) { // for each variable
  103. int cbneed = 0;
  104. if ( (szValues[i] == NULL) || !(cbneed = lstrlen(szValues[i])))
  105. continue;
  106. cbneed++; // add for nul
  107. if (0 == strncmp(szVars[i], pchSrc, cbvar)) {
  108. // found something we can expand
  109. if ((cbLen + cbneed) >= cbBuffer) {
  110. // out of buffer space
  111. *pchOut = '\0'; // term
  112. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  113. goto Exit;
  114. }
  115. lstrcpy(pchOut, szValues[i]);
  116. cbLen += (cbneed -1); //don't count the nul
  117. pchSrc += cbvar; // skip past the var in pchSrc
  118. pchOut += (cbneed -1); // skip past dir in pchOut
  119. hr = S_OK;
  120. goto Exit;
  121. }
  122. }
  123. Exit:
  124. DEBUG_LEAVE(hr);
  125. return hr;
  126. }
  127. // ---------------------------------------------------------------------------
  128. // %%Function: CSetupHook::TranslateString
  129. // ---------------------------------------------------------------------------
  130. HRESULT
  131. CSetupHook::TranslateString()
  132. {
  133. DEBUG_ENTER((DBG_DOWNLOAD,
  134. Hresult,
  135. "CSetupHook::TranslateString",
  136. "this=%#x",
  137. this
  138. ));
  139. Assert(m_pdl);
  140. Assert(m_szInf);
  141. Assert(m_szHook);
  142. HRESULT hr = S_OK;
  143. DWORD_PTR flags = (g_dwCodeDownloadSetupFlags & CDSF_USE_SETUPAPI)?RSC_FLAG_SETUPAPI:0;
  144. // there's a command line in the run= command.
  145. // have advpack tranalate it for us.
  146. DWORD dwBufferSize = 0;
  147. DWORD dwRequiredSize = 0;
  148. // get reqd size to hold expanded string
  149. #ifdef WX86
  150. if (m_pdl->GetCodeDownload()->GetMultiArch()->GetRequiredArch() == PROCESSOR_ARCHITECTURE_INTEL) {
  151. hr = g_RunSetupHook.TranslateInfStringX86(
  152. m_pdl->GetCodeDownload()->GetMainInf(), // inf name
  153. NULL, // use DefaultInstall
  154. m_szHook, // hook section name
  155. "run", // key name
  156. NULL, // find out size reqd.
  157. dwBufferSize,
  158. &dwRequiredSize,
  159. (PVOID)flags);
  160. } else {
  161. hr = g_RunSetupHook.TranslateInfString(
  162. m_pdl->GetCodeDownload()->GetMainInf(), // inf name
  163. NULL, // use DefaultInstall
  164. m_szHook, // hook section name
  165. "run", // key name
  166. NULL, // find out size reqd.
  167. dwBufferSize,
  168. &dwRequiredSize,
  169. (PVOID)flags);
  170. }
  171. #else
  172. hr = g_RunSetupHook.TranslateInfString(
  173. m_pdl->GetCodeDownload()->GetMainInf(), // inf name
  174. NULL, // use DefaultInstall
  175. m_szHook, // hook section name
  176. "run", // key name
  177. NULL, // find out size reqd.
  178. dwBufferSize,
  179. &dwRequiredSize,
  180. (PVOID)flags);
  181. #endif
  182. if (FAILED(hr))
  183. goto Exit;
  184. Assert(dwRequiredSize);
  185. if (m_szInf)
  186. SAFEDELETE(m_szInf);
  187. m_szInf= new char [(dwBufferSize = dwRequiredSize+1)];
  188. if (!m_szInf) {
  189. hr = E_OUTOFMEMORY;
  190. goto Exit;
  191. }
  192. // the real thing
  193. #ifdef WX86
  194. if (m_pdl->GetCodeDownload()->GetMultiArch()->GetRequiredArch() == PROCESSOR_ARCHITECTURE_INTEL) {
  195. hr = g_RunSetupHook.TranslateInfStringX86(
  196. m_pdl->GetCodeDownload()->GetMainInf(), // inf name
  197. NULL, // use DefaultInstall
  198. m_szHook, // hook section name
  199. "run", // key name
  200. m_szInf,
  201. dwBufferSize,
  202. &dwRequiredSize,
  203. (PVOID)flags);
  204. } else {
  205. hr = g_RunSetupHook.TranslateInfString(
  206. m_pdl->GetCodeDownload()->GetMainInf(), // inf name
  207. NULL, // use DefaultInstall
  208. m_szHook, // hook section name
  209. "run", // key name
  210. m_szInf,
  211. dwBufferSize,
  212. &dwRequiredSize,
  213. (PVOID)flags);
  214. }
  215. #else
  216. hr = g_RunSetupHook.TranslateInfString(
  217. m_pdl->GetCodeDownload()->GetMainInf(), // inf name
  218. NULL, // use DefaultInstall
  219. m_szHook, // hook section name
  220. "run", // key name
  221. m_szInf,
  222. dwBufferSize,
  223. &dwRequiredSize,
  224. (PVOID)flags);
  225. #endif
  226. Exit:
  227. DEBUG_LEAVE(hr);
  228. return hr;
  229. }
  230. // ---------------------------------------------------------------------------
  231. // %%Function: CSetupHook::ExpandCommandLine
  232. // ---------------------------------------------------------------------------
  233. HRESULT
  234. CSetupHook::ExpandCommandLine(
  235. LPSTR szSrc,
  236. LPSTR szBuf,
  237. DWORD cbBuffer,
  238. const char * szVars[],
  239. const char * szValues[])
  240. {
  241. DEBUG_ENTER((DBG_DOWNLOAD,
  242. Hresult,
  243. "CSetupHook::ExpandCommandLine",
  244. "%.80q, %.80q, %#x, %#x, %#x",
  245. szSrc, szBuf, cbBuffer, szVars, szValues
  246. ));
  247. Assert(cbBuffer);
  248. HRESULT hr = S_FALSE;
  249. LPSTR pchSrc = szSrc; // start parsing at begining of cmdline
  250. LPSTR pchOut = szBuf; // set at begin of out buffer
  251. DWORD cbLen = 0;
  252. while (*pchSrc) {
  253. // look for match of any of our env vars
  254. if (*pchSrc == '%') {
  255. HRESULT hr1 = ExpandVar(pchSrc, pchOut, cbLen, // all passed by ref!
  256. cbBuffer, szVars, szValues);
  257. if (FAILED(hr1)) {
  258. hr = hr1;
  259. goto Exit;
  260. }
  261. if (hr1 == S_OK) { // expand var expanded this
  262. hr = hr1;
  263. continue;
  264. }
  265. }
  266. // copy till the next % or nul
  267. if ((cbLen + 1) < cbBuffer) {
  268. *pchOut++ = *pchSrc++;
  269. cbLen++;
  270. } else {
  271. // out of buffer space
  272. *pchOut = '\0'; // term
  273. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  274. goto Exit;
  275. }
  276. }
  277. *pchOut = '\0'; // term
  278. Exit:
  279. DEBUG_LEAVE(hr);
  280. return hr;
  281. }
  282. // ---------------------------------------------------------------------------
  283. // %%Function: CSetupHook::Run
  284. // ---------------------------------------------------------------------------
  285. HRESULT
  286. CSetupHook::Run()
  287. {
  288. DEBUG_ENTER((DBG_DOWNLOAD,
  289. Hresult,
  290. "CSetupHook::Run",
  291. "this=%#x",
  292. this
  293. ));
  294. Assert(m_pdl);
  295. CCodeDownload *pcdl = m_pdl->GetCodeDownload();
  296. Assert(pcdl);
  297. HWND hWnd = pcdl->GetClientBinding()->GetHWND();
  298. HANDLE hExe = INVALID_HANDLE_VALUE;
  299. HRESULT hr = S_OK;
  300. DWORD flags = m_flags;
  301. #define SIZE_CMD_LINE 2048
  302. char szBuf[SIZE_CMD_LINE]; // enough for commandline
  303. DWORD nStatusText = 0;
  304. WCHAR szStatusText[SIZE_CMD_LINE];
  305. Assert(m_szInf);
  306. // BEGIN NOTE: add vars and values in matching order
  307. // add a var by adding a new define VAR_NEW_VAR = NUM_VARS++
  308. const char *szVars[] = {
  309. #define VAR_EXTRACT_DIR 0 // dir hook CABs are expanded to temporarily
  310. "%EXTRACT_DIR%",
  311. #define VAR_OBJECT_DIR 1 // dir the main object will be installed to
  312. "%OBJECT_DIR%", // usually activex cache dir, sometimes
  313. // a conflict dir or dir of prev version
  314. // of object
  315. #define VAR_SRC_URL 2 // CODEBASE where we got this from
  316. "%SRC_URL%",
  317. #define NUM_VARS 3
  318. ""
  319. };
  320. char szSrcURL[INTERNET_MAX_URL_LENGTH];
  321. LPCWSTR wzSrcURL = NULL;
  322. szSrcURL[0] = '\0';
  323. if ((wzSrcURL = GetSrcURL()) != NULL) {
  324. WideCharToMultiByte(CP_ACP, 0, wzSrcURL, -1, szSrcURL, MAX_PATH, 0, 0);
  325. }
  326. const char *szValues[NUM_VARS + 1];
  327. szValues[VAR_EXTRACT_DIR] = GetHookDir();
  328. szValues[VAR_OBJECT_DIR] = GetObjectDir();
  329. szValues[VAR_SRC_URL] = szSrcURL;
  330. szValues[NUM_VARS] = NULL;
  331. // END NOTE: add vars and values in matching order
  332. if (m_flags & RSC_FLAG_INF) {
  333. flags |= RSC_FLAG_QUIET;
  334. if (g_dwCodeDownloadSetupFlags & CDSF_USE_SETUPAPI)
  335. flags |= RSC_FLAG_SETUPAPI;
  336. // get fully qualified name for INF
  337. if (GetHookDir()) {
  338. if (!catDirAndFile(szBuf, SIZE_CMD_LINE, GetHookDir(),
  339. m_szInf)) {
  340. hr = E_UNEXPECTED;
  341. goto Exit;
  342. }
  343. } else {
  344. // no hook dir
  345. Assert(m_pdl->GetExtn() != FILEXTN_CAB);
  346. StrNCpy(szBuf, m_pdl->GetFileName(), sizeof(szBuf));
  347. }
  348. } else {
  349. // cmd line
  350. // have ADVPACK expand out custom LDID vars in run= cmdline
  351. // then we will process for our own vars
  352. // this allows the user to specify custom dirs thru the INF
  353. // and use it in the cmd line off registry keys
  354. hr = TranslateString();
  355. if (FAILED(hr))
  356. goto Exit;
  357. // look for and substitute variables like %EXTRACT_DIR%
  358. // and expand out the command line
  359. hr = ExpandCommandLine(m_szInf, szBuf, SIZE_CMD_LINE, szVars, szValues);
  360. if (FAILED(hr))
  361. goto Exit;
  362. hr = S_OK; // reset
  363. }
  364. nStatusText = MultiByteToWideChar(CP_ACP, 0, szBuf,
  365. -1, szStatusText, SIZE_CMD_LINE);
  366. #ifdef WX86
  367. if (m_pdl->GetCodeDownload()->GetMultiArch()->GetRequiredArch() == PROCESSOR_ARCHITECTURE_INTEL) {
  368. hr = g_RunSetupHook.RunSetupCommandX86(hWnd,
  369. szBuf,
  370. m_szInfSection,
  371. // extracted files in this dir
  372. (char *)((GetHookDir())?GetHookDir():m_pdl->GetCodeDownload()->GetCacheDir()),
  373. NULL, /*title*/
  374. &hExe, // handle to wait on for EXE
  375. flags,
  376. NULL);
  377. } else {
  378. hr = g_RunSetupHook.RunSetupCommand(hWnd,
  379. szBuf,
  380. m_szInfSection,
  381. // extracted files in this dir
  382. (char *)((GetHookDir())?GetHookDir():m_pdl->GetCodeDownload()->GetCacheDir()),
  383. NULL, /*title*/
  384. &hExe, // handle to wait on for EXE
  385. flags,
  386. NULL);
  387. }
  388. #else
  389. hr = g_RunSetupHook.RunSetupCommand(hWnd,
  390. szBuf,
  391. m_szInfSection,
  392. // extracted files in this dir
  393. (char *)((GetHookDir())?GetHookDir():m_pdl->GetCodeDownload()->GetCacheDir()),
  394. NULL, /*title*/
  395. &hExe, // handle to wait on for EXE
  396. flags,
  397. NULL);
  398. #endif
  399. if (SUCCEEDED(hr) && (m_flags & RSC_FLAG_INF)) {
  400. // pass a notification to reboot
  401. if (hr == ERROR_SUCCESS_REBOOT_REQUIRED) {
  402. ICodeInstall* pCodeInstall = pcdl->GetICodeInstall();
  403. if (pCodeInstall) {
  404. pCodeInstall->OnCodeInstallProblem(
  405. CIP_NEED_REBOOT,
  406. NULL, szStatusText, 0);
  407. }
  408. pcdl->SetRebootRequired();
  409. hr = S_OK;
  410. }
  411. }
  412. // if we launched an EXE then we would have to mark as waiting for it
  413. if (hExe != INVALID_HANDLE_VALUE) {
  414. pcdl->SetWaitingForEXE(szBuf, FALSE /*don't delete EXE */);
  415. pcdl->SetWaitingForEXEHandle(hExe);
  416. }
  417. Exit:
  418. if (FAILED(hr)) {
  419. pcdl->CodeDownloadDebugOut(DEB_CODEDL, TRUE, ID_CDLDBG_RUNSETUPHOOK_FAILED, hr, m_szInf);
  420. } else {
  421. pcdl->CodeDownloadDebugOut(DEB_CODEDL, TRUE, ID_CDLDBG_HOOK_COMPLETE, m_szHook);
  422. }
  423. SetState(INSTALL_DONE);
  424. DEBUG_LEAVE(hr);
  425. return hr;
  426. }