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.

1256 lines
32 KiB

  1. // GenericClass.cpp: implementation of the CGenericClass class.
  2. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  3. //
  4. //////////////////////////////////////////////////////////////////////
  5. #include "precomp.h"
  6. #include "GenericClass.h"
  7. #include <wininet.h>
  8. #define READ_HANDLE 0
  9. #define WRITE_HANDLE 1
  10. #include "ExtendString.h"
  11. #include "ExtendQuery.h"
  12. #include <scopeguard.h>
  13. CRITICAL_SECTION CGenericClass::m_cs;
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. CGenericClass::CGenericClass(CRequestObject *pObj, IWbemServices *pNamespace, IWbemContext *pCtx)
  18. {
  19. m_pRequest = pObj;
  20. m_pNamespace = pNamespace;
  21. m_pCtx = pCtx;
  22. m_pObj = NULL;
  23. m_pClassForSpawning = NULL;
  24. }
  25. CGenericClass::~CGenericClass()
  26. {
  27. }
  28. void CGenericClass::CleanUp()
  29. {
  30. if(m_pClassForSpawning){
  31. m_pClassForSpawning->Release();
  32. m_pClassForSpawning = NULL;
  33. }
  34. }
  35. void CGenericClass::CheckMSI(UINT uiStatus)
  36. {
  37. if(uiStatus == E_OUTOFMEMORY){
  38. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  39. }else if(uiStatus != ERROR_SUCCESS){
  40. throw ConvertError(uiStatus);
  41. }
  42. }
  43. HRESULT CGenericClass::CheckOpen(UINT uiStatus)
  44. {
  45. switch(uiStatus){
  46. case ERROR_SUCCESS:
  47. return WBEM_S_NO_ERROR;
  48. case ERROR_ACCESS_DENIED:
  49. return WBEM_E_PRIVILEGE_NOT_HELD;
  50. default:
  51. return WBEM_E_FAILED;
  52. }
  53. }
  54. HRESULT CGenericClass::SetSinglePropertyPath(WCHAR wcProperty[])
  55. {
  56. if( m_pRequest->m_iPropCount >= MSI_KEY_LIST_SIZE) {
  57. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  58. }
  59. if(m_pRequest->m_iValCount > m_pRequest->m_iPropCount){
  60. m_pRequest->m_Property[m_pRequest->m_iPropCount] = SysAllocString(wcProperty);
  61. if(!m_pRequest->m_Property[(m_pRequest->m_iPropCount)++])
  62. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  63. }
  64. return S_OK;
  65. }
  66. WCHAR * CGenericClass::GetFirstGUID(WCHAR wcIn[], WCHAR wcOut[])
  67. {
  68. // safe operation
  69. // tested outside of that call
  70. wcscpy(wcOut, wcIn);
  71. wcOut[38] = NULL;
  72. return wcOut;
  73. }
  74. WCHAR * CGenericClass::RemoveFinalGUID(WCHAR wcIn[], WCHAR wcOut[])
  75. {
  76. // safe operation
  77. // tested outside of that call
  78. wcscpy(wcOut, wcIn);
  79. wcOut[wcslen(wcOut) - 38] = NULL;
  80. return wcOut;
  81. }
  82. HRESULT CGenericClass::SpawnAnInstance(IWbemServices *pNamespace, IWbemContext *pCtx,
  83. IWbemClassObject **pObj, BSTR bstrName)
  84. {
  85. HRESULT hr = WBEM_S_NO_ERROR;
  86. if(!m_pClassForSpawning){
  87. //Get ourselves an instance
  88. if(FAILED(hr = m_pNamespace->GetObject(bstrName, 0, m_pCtx, &m_pClassForSpawning, NULL))){
  89. *pObj = NULL;
  90. return hr;
  91. }
  92. }
  93. hr = m_pClassForSpawning->SpawnInstance(0, pObj);
  94. return hr;
  95. }
  96. HRESULT CGenericClass::SpawnAnInstance(IWbemClassObject **pObj)
  97. {
  98. HRESULT hr = WBEM_S_NO_ERROR;
  99. if(!m_pClassForSpawning){
  100. //Get ourselves an instance
  101. if(FAILED(hr = m_pNamespace->GetObject(m_pRequest->m_bstrClass, 0, m_pCtx,
  102. &m_pClassForSpawning, NULL))){
  103. *pObj = NULL;
  104. return hr;
  105. }
  106. }
  107. hr = m_pClassForSpawning->SpawnInstance(0, pObj);
  108. return hr;
  109. }
  110. HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, WCHAR *wcValue)
  111. {
  112. HRESULT hr = WBEM_S_NO_ERROR;
  113. CHeap_Exception he(CHeap_Exception::E_ALLOCATION_ERROR);
  114. WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
  115. if(!wcTmp)
  116. throw he;
  117. mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
  118. BSTR bstrName = SysAllocString(wcTmp);
  119. free((void *)wcTmp);
  120. if(!bstrName)
  121. throw he;
  122. VARIANT vp;
  123. VariantInit(&vp);
  124. V_VT(&vp) = VT_BSTR;
  125. V_BSTR(&vp) = SysAllocString(wcValue);
  126. if(!V_BSTR(&vp)){
  127. SysFreeString(bstrName);
  128. throw he;
  129. }
  130. if((wcValue == NULL) || (0 != _wcsicmp(wcValue, L""))){
  131. hr = pObj->Put(bstrName, 0, &vp, NULL);
  132. if(FAILED(hr)){
  133. SysFreeString(bstrName);
  134. VariantClear(&vp);
  135. throw hr;
  136. }
  137. }else hr = WBEM_E_FAILED;
  138. SysFreeString(bstrName);
  139. VariantClear(&vp);
  140. return hr;
  141. }
  142. HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, int iValue)
  143. {
  144. HRESULT hr = WBEM_S_NO_ERROR;
  145. WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
  146. if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  147. mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
  148. BSTR bstrName = SysAllocString(wcTmp);
  149. free((void *)wcTmp);
  150. if(!bstrName)
  151. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
  152. if(iValue != MSI_NULL_INTEGER){
  153. VARIANT pv;
  154. VariantInit(&pv);
  155. V_VT(&pv) = VT_I4;
  156. V_I4(&pv) = iValue;
  157. hr = pObj->Put(bstrName, 0, &pv, NULL);
  158. VariantClear(&pv);
  159. if(FAILED(hr)){
  160. SysFreeString(bstrName);
  161. throw hr;
  162. }
  163. }else hr = WBEM_E_FAILED;
  164. SysFreeString(bstrName);
  165. return hr;
  166. }
  167. HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, float dValue)
  168. {
  169. HRESULT hr = WBEM_S_NO_ERROR;
  170. WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
  171. if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  172. mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
  173. BSTR bstrName = SysAllocString(wcTmp);
  174. free((void *)wcTmp);
  175. if(!bstrName)
  176. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
  177. VARIANT pv;
  178. VariantInit(&pv);
  179. V_VT(&pv) = VT_R4;
  180. V_R4(&pv) = dValue;
  181. hr = pObj->Put(bstrName, 0, &pv, NULL);
  182. SysFreeString(bstrName);
  183. VariantClear(&pv);
  184. if(FAILED(hr))
  185. throw hr;
  186. return hr;
  187. }
  188. HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, bool bValue)
  189. {
  190. HRESULT hr = WBEM_S_NO_ERROR;
  191. WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
  192. if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  193. mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
  194. BSTR bstrName = SysAllocString(wcTmp);
  195. free((void *)wcTmp);
  196. if(!bstrName)
  197. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  198. VARIANT pv;
  199. VariantInit(&pv);
  200. V_VT(&pv) = VT_BOOL;
  201. if(bValue) V_BOOL(&pv) = VARIANT_TRUE;
  202. else V_BOOL(&pv) = VARIANT_FALSE;
  203. hr = pObj->Put(bstrName, 0, &pv, NULL);
  204. SysFreeString(bstrName);
  205. VariantClear(&pv);
  206. if(FAILED(hr))
  207. throw hr;
  208. return hr;
  209. }
  210. HRESULT CGenericClass::PutKeyProperty(IWbemClassObject *pObj, const char *wcProperty, WCHAR *wcValue,
  211. bool *bKey, CRequestObject *pRequest)
  212. {
  213. HRESULT hr = WBEM_S_NO_ERROR;
  214. WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
  215. if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  216. mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
  217. BSTR bstrName = SysAllocString(wcTmp);
  218. free((void *)wcTmp);
  219. if(!bstrName)
  220. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
  221. VARIANT pv;
  222. VariantInit(&pv);
  223. V_VT(&pv) = VT_BSTR;
  224. #ifdef _STRIP_ESCAPED_CHARS
  225. V_BSTR(&pv) = SysAllocString(ConvertToASCII(wcValue));
  226. #else
  227. V_BSTR(&pv) = SysAllocString(wcValue);
  228. #endif //_STRIP_ESCAPED_CHARS
  229. if(!V_BSTR(&pv))
  230. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
  231. if((wcValue == NULL) || (0 != wcscmp(wcValue, L""))){
  232. hr = pObj->Put(bstrName, 0, &pv, NULL);
  233. if(FAILED(hr)){
  234. SysFreeString(bstrName);
  235. VariantClear(&pv);
  236. throw hr;
  237. }
  238. // Find the keys
  239. *bKey = false;
  240. int iPos = -1;
  241. if(FindIn(pRequest->m_Property, bstrName, &iPos) &&
  242. FindIn(pRequest->m_Value, V_BSTR(&pv), &iPos)) *bKey = true;
  243. }else hr = WBEM_E_FAILED;
  244. SysFreeString(bstrName);
  245. VariantClear(&pv);
  246. return hr;
  247. }
  248. HRESULT CGenericClass::PutKeyProperty(IWbemClassObject *pObj, const char *wcProperty, int iValue,
  249. bool *bKey, CRequestObject *pRequest)
  250. {
  251. HRESULT hr = WBEM_S_NO_ERROR;
  252. WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
  253. if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  254. mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
  255. BSTR bstrName = SysAllocString(wcTmp);
  256. free((void *)wcTmp);
  257. if(!bstrName)
  258. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
  259. VARIANT pv;
  260. WCHAR wcBuf[BUFF_SIZE];
  261. if(iValue != MSI_NULL_INTEGER){
  262. VariantInit(&pv);
  263. V_VT(&pv) = VT_I4;
  264. V_I4(&pv) = iValue;
  265. hr = pObj->Put(bstrName, 0, &pv, NULL);
  266. VariantClear(&pv);
  267. if(FAILED(hr))
  268. {
  269. SysFreeString(bstrName);
  270. throw hr;
  271. }
  272. // Find the keys
  273. _itow(iValue, wcBuf, 10);
  274. BSTR bstrValue = SysAllocString(wcBuf);
  275. if(!bstrValue)
  276. {
  277. SysFreeString(bstrName);
  278. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  279. }
  280. *bKey = false;
  281. int iPos = -1;
  282. if(FindIn(pRequest->m_Property, bstrName, &iPos) &&
  283. FindIn(pRequest->m_Value, bstrValue, &iPos)) *bKey = true;
  284. SysFreeString(bstrValue);
  285. }else hr = WBEM_E_FAILED;
  286. SysFreeString(bstrName);
  287. return hr;
  288. }
  289. bool CGenericClass::FindIn(BSTR bstrProp[], BSTR bstrSearch, int *iPos)
  290. {
  291. int i = 0;
  292. if(*iPos == (-1))
  293. {
  294. while(bstrProp[i] != NULL)
  295. {
  296. if(0 == _wcsicmp(bstrProp[i], bstrSearch))
  297. {
  298. *iPos = i;
  299. return true;
  300. }
  301. i++;
  302. }
  303. }
  304. else
  305. {
  306. if(0 == _wcsicmp(bstrProp[*iPos], bstrSearch))
  307. {
  308. return true;
  309. }
  310. }
  311. return false;
  312. }
  313. bool CGenericClass::GetView ( MSIHANDLE *phProduct,
  314. WCHAR *wcPackage,
  315. WCHAR *wcQuery,
  316. WCHAR *wcTable,
  317. BOOL bCloseProduct,
  318. BOOL bCloseDatabase
  319. )
  320. {
  321. return msidata.GetView ( phProduct, wcPackage, wcQuery, wcTable, bCloseProduct, bCloseDatabase );
  322. }
  323. HRESULT CGenericClass::GetProperty(IWbemClassObject *pObj, const char *cProperty, BSTR *wcValue)
  324. {
  325. HRESULT hr = WBEM_S_NO_ERROR;
  326. VARIANT v;
  327. WCHAR wcTmp[BUFF_SIZE];
  328. CHeap_Exception he(CHeap_Exception::E_ALLOCATION_ERROR);
  329. BSTR bstrProp = SysAllocString(TcharToWchar(cProperty, wcTmp));
  330. if(!bstrProp)
  331. throw he;
  332. ON_BLOCK_EXIT ( SysFreeString, bstrProp ) ;
  333. VariantInit(&v);
  334. ON_BLOCK_EXIT ( VariantClear, &v ) ;
  335. if(SUCCEEDED(hr = pObj->Get(bstrProp, 0, &v, NULL, NULL))){
  336. if( V_VT( &v ) == VT_BSTR )
  337. {
  338. if ( wcslen ( V_BSTR ( &v ) ) > INTERNET_MAX_PATH_LENGTH )
  339. {
  340. return WBEM_E_INVALID_METHOD_PARAMETERS;
  341. }
  342. *wcValue = SysAllocString(V_BSTR(&v));
  343. }
  344. else
  345. {
  346. *wcValue = SysAllocString(L"");
  347. }
  348. if(!wcValue)
  349. throw he;
  350. }
  351. return hr;
  352. }
  353. HRESULT CGenericClass::GetProperty(IWbemClassObject *pObj, const char *cProperty, int *piValue)
  354. {
  355. HRESULT hr = WBEM_S_NO_ERROR;
  356. VARIANT v;
  357. WCHAR wcTmp[BUFF_SIZE];
  358. CHeap_Exception he(CHeap_Exception::E_ALLOCATION_ERROR);
  359. BSTR bstrProp = SysAllocString(TcharToWchar(cProperty, wcTmp));
  360. if(!bstrProp)
  361. throw he;
  362. VariantInit(&v);
  363. if(SUCCEEDED(hr = pObj->Get(bstrProp, 0, &v, NULL, NULL))){
  364. if(V_VT(&v) == VT_I4) *piValue = V_I4(&v);
  365. else *piValue = 0;
  366. }
  367. SysFreeString(bstrProp);
  368. VariantClear(&v);
  369. return hr;
  370. }
  371. HRESULT CGenericClass::GetProperty(IWbemClassObject *pObj, const char *cProperty, bool *pbValue)
  372. {
  373. HRESULT hr = WBEM_S_NO_ERROR;
  374. VARIANT v;
  375. WCHAR wcTmp[BUFF_SIZE];
  376. CHeap_Exception he(CHeap_Exception::E_ALLOCATION_ERROR);
  377. BSTR bstrProp = SysAllocString(TcharToWchar(cProperty, wcTmp));
  378. if(!bstrProp)
  379. throw he;
  380. VariantInit(&v);
  381. if(SUCCEEDED(hr = pObj->Get(bstrProp, 0, &v, NULL, NULL))){
  382. if((V_VT(&v) == VT_BOOL) & V_BOOL(&v)) *pbValue = true;
  383. else *pbValue = false;
  384. }
  385. SysFreeString(bstrProp);
  386. VariantClear(&v);
  387. return hr;
  388. }
  389. /****************************************************************************
  390. *
  391. * CGenericClass::LaunchProcess()
  392. *
  393. * In:
  394. * wcCommandLine - the commandline to pass to msimeth
  395. *
  396. * Out:
  397. * uiStatus - The variable that will recieve the return value
  398. * from the method call
  399. *
  400. *
  401. * this method will handle method execution on NT4, where security
  402. * restrictions prevent calling another DCOM server with an impersonating
  403. * thread token. This method will launch another process to handle the
  404. * opperation after setting up a pipe for passing status messages from the
  405. * external process back to the provider.
  406. *
  407. *****************************************************************************/
  408. HRESULT CGenericClass::LaunchProcess(WCHAR *wcAction, WCHAR *wcCommandLine, UINT *uiStatus)
  409. {
  410. HRESULT hr = WBEM_E_FAILED;
  411. //check to see if server already running
  412. HANDLE hMutex = CreateMutex(NULL, TRUE, TEXT("MSIPROV_METHODS_SERVER"));
  413. if(hMutex){
  414. IWbemClassObject *pObj = NULL;
  415. BSTR bstrProcess = SysAllocString(L"Win32_Process");
  416. SetFileApisToOEM();
  417. HANDLE hPipe = CreateNamedPipe(L"\\\\.\\pipe\\msimeth_pipe", PIPE_ACCESS_INBOUND,
  418. (PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT), PIPE_UNLIMITED_INSTANCES,
  419. 10000, 10000, 50000, NULL);
  420. if(SUCCEEDED(hr = m_pNamespace->GetObject(bstrProcess, 0, m_pCtx, &pObj, NULL))){
  421. IWbemClassObject *pInParam = NULL;
  422. IWbemClassObject *pOutParam = NULL;
  423. BSTR bstrCreate = SysAllocString(L"Create");
  424. // get the method paramater objects
  425. if(SUCCEEDED(hr = pObj->GetMethod(bstrCreate, 0, &pInParam, &pOutParam))){
  426. VARIANT v;
  427. BSTR bstrCommandLine = SysAllocString(L"CommandLine");
  428. IWbemClassObject *pStartup = NULL;
  429. VariantInit(&v);
  430. V_VT(&v) = VT_BSTR;
  431. WCHAR wcCommand[BUFF_SIZE];
  432. WCHAR wcTmp[10];
  433. UINT uiSize = BUFF_SIZE;
  434. GetSystemDirectoryW(wcCommand, uiSize);
  435. wcscat(wcCommand, L"\\wbem\\msimeth.exe ");
  436. wcscat(wcCommand, wcAction);
  437. wcscat(wcCommand, L" ");
  438. wcscat(wcCommand, _itow(m_pRequest->m_iThreadID, wcTmp, 10));
  439. wcscat(wcCommand, L" ");
  440. wcscat(wcCommand, wcCommandLine);
  441. V_BSTR(&v) = SysAllocString(wcCommand);
  442. // populate the in parameters
  443. if(SUCCEEDED(hr = pInParam->Put(bstrCommandLine, 0, &v, NULL))){
  444. VariantClear(&v);
  445. BSTR bstrProcessStartup = SysAllocString(L"Win32_ProcessStartup");
  446. IWbemClassObject *pStartupObj = NULL;
  447. if(SUCCEEDED(hr = m_pNamespace->GetObject(bstrProcessStartup, 0, m_pCtx,
  448. &pStartupObj, NULL))){
  449. IWbemClassObject *pStartupInst = NULL;
  450. if(SUCCEEDED(hr = pStartupObj->SpawnInstance(0, &pStartupInst))){
  451. LPVOID pEnv = GetEnvironmentStrings();
  452. WCHAR *pwcVar = (WCHAR *)pEnv;
  453. SAFEARRAYBOUND sbArrayBounds ;
  454. long lCount = GetVarCount(pEnv);
  455. sbArrayBounds.cElements = lCount;
  456. sbArrayBounds.lLbound = 0;
  457. if(V_ARRAY(&v) = SafeArrayCreate(VT_BSTR, 1, &sbArrayBounds)){
  458. V_VT(&v) = VT_BSTR | VT_ARRAY ;
  459. BSTR bstrVal;
  460. //get the environment variables into a VARIANT
  461. for(long j = 0; j < lCount; j++){
  462. bstrVal = SysAllocString(pwcVar);
  463. SafeArrayPutElement(V_ARRAY(&v), &j, bstrVal);
  464. SysFreeString(bstrVal);
  465. pwcVar = GetNextVar(pwcVar);
  466. }
  467. BSTR bstrEnvironmentVariables = SysAllocString(L"EnvironmentVariables");
  468. if(SUCCEEDED(hr = pStartupInst->Put(bstrEnvironmentVariables, 0,
  469. &v, NULL))){
  470. VariantClear(&v);
  471. V_VT(&v) = VT_UNKNOWN;
  472. V_UNKNOWN(&v) = (IDispatch *)pStartupInst;
  473. pStartupInst->AddRef();
  474. BSTR bstrProcessStartupInformation = SysAllocString(L"ProcessStartupInformation");
  475. hr = pInParam->Put(bstrProcessStartupInformation, 0, &v, NULL);
  476. SysFreeString(bstrProcessStartupInformation);
  477. }
  478. SysFreeString(bstrEnvironmentVariables);
  479. }
  480. FreeEnvironmentStrings((LPWSTR)pEnv);
  481. pStartupInst->Release();
  482. }
  483. pStartupObj->Release();
  484. }
  485. SysFreeString(bstrProcessStartup);
  486. //we've no created our input object, so let's make the call
  487. if(SUCCEEDED(hr = m_pNamespace->ExecMethod(bstrProcess, bstrCreate, 0,
  488. m_pCtx, pInParam, &pOutParam, NULL))){
  489. VariantClear(&v);
  490. BSTR bstrReturnValue = SysAllocString(L"ReturnValue");
  491. if(SUCCEEDED(hr = pOutParam->Get(bstrReturnValue, 0, &v, NULL, NULL))){
  492. hr = V_I4(&v);
  493. VariantClear(&v);
  494. if(hr == 0){
  495. BSTR bstrProcessID = SysAllocString(L"ProcessID");
  496. if(SUCCEEDED(hr = pOutParam->Get(bstrProcessID, 0, &v, NULL, NULL))){
  497. //open process handle to check for exit
  498. HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE,
  499. (DWORD)V_I4(&v));
  500. ReleaseMutex(hMutex);
  501. if(hProcess){
  502. BOOL bRead = FALSE;
  503. DWORD dwRead = 0;
  504. WCHAR wcBuf[BUFF_SIZE];
  505. int nExitCode = STILL_ACTIVE;
  506. if(!GetExitCodeProcess(hProcess, (unsigned long*)&nExitCode)){
  507. hr = GetLastError();
  508. }
  509. /////////////////////////////////////////////////
  510. // Handle status messages as they are recieved
  511. while(nExitCode == STILL_ACTIVE){
  512. //synchronized pipe access
  513. // WaitForSingleObject(hMutex, INFINITE);
  514. bRead = ReadFile(hPipe, wcBuf, BUFF_SIZE, &dwRead, NULL);
  515. // ReleaseMutex(hMutex);
  516. if(!bRead){
  517. switch(GetLastError()){
  518. case ERROR_MORE_DATA:
  519. //deal with unable to read whole message
  520. break;
  521. case ERROR_HANDLE_EOF:
  522. break;
  523. }
  524. }
  525. if(bRead && dwRead){
  526. //do some parsing, then...
  527. int iContext = _wtoi(wcstok(wcBuf, L"~"));
  528. UINT uiMessageType = _wtoi(wcstok(NULL, L"~"));
  529. LPWSTR lpwMessage = wcstok(NULL, L"\n");
  530. //process the message
  531. MyEventHandler(m_pRequest, uiMessageType, lpwMessage);
  532. }
  533. if(!GetExitCodeProcess(hProcess, (unsigned long*)&nExitCode)){
  534. hr = GetLastError();
  535. break;
  536. }
  537. }
  538. *uiStatus = nExitCode;
  539. CloseHandle(hPipe);
  540. }
  541. }
  542. SysFreeString(bstrProcessID);
  543. }else{
  544. hr = WBEM_E_FAILED;
  545. }
  546. }
  547. SysFreeString(bstrReturnValue);
  548. }
  549. }
  550. pInParam->Release();
  551. pOutParam->Release();
  552. VariantClear(&v);
  553. }
  554. SysFreeString(bstrCreate);
  555. pObj->Release();
  556. }
  557. SysFreeString(bstrProcess);
  558. }
  559. if(hMutex){
  560. CloseHandle(hMutex);
  561. hMutex = NULL;
  562. }
  563. return hr;
  564. }
  565. INSTALLUI_HANDLER CGenericClass::SetupExternalUI()
  566. {
  567. g_fpMsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
  568. INSTALLUI_HANDLER ui = NULL;
  569. ui = g_fpMsiSetExternalUIW ( MyEventHandler,
  570. (
  571. INSTALLLOGMODE_PROGRESS |
  572. INSTALLLOGMODE_ACTIONDATA |
  573. INSTALLLOGMODE_INFO |
  574. INSTALLLOGMODE_WARNING |
  575. INSTALLLOGMODE_ACTIONSTART
  576. ),
  577. m_pRequest
  578. );
  579. g_fpMsiEnableLogW (
  580. ( INSTALLLOGMODE_ACTIONDATA |
  581. INSTALLLOGMODE_INFO |
  582. INSTALLLOGMODE_FATALEXIT |
  583. INSTALLLOGMODE_ERROR |
  584. INSTALLLOGMODE_WARNING |
  585. INSTALLLOGMODE_USER |
  586. INSTALLLOGMODE_VERBOSE |
  587. INSTALLLOGMODE_RESOLVESOURCE |
  588. INSTALLLOGMODE_OUTOFDISKSPACE |
  589. INSTALLLOGMODE_COMMONDATA |
  590. INSTALLLOGMODE_PROPERTYDUMP |
  591. INSTALLLOGMODE_ACTIONSTART
  592. ),
  593. g_wcpLoggingDir,
  594. INSTALLLOGATTRIBUTES_APPEND
  595. );
  596. return ui;
  597. }
  598. void CGenericClass::RestoreExternalUI( INSTALLUI_HANDLER ui )
  599. {
  600. g_fpMsiSetExternalUIW ( ui, 0, NULL );
  601. }
  602. WCHAR * CGenericClass::GetNextVar(WCHAR *pwcStart)
  603. {
  604. WCHAR *pwc = pwcStart;
  605. //get to end of variable
  606. while(*pwc){ pwc++; }
  607. return ++pwc;
  608. }
  609. long CGenericClass::GetVarCount(void * pEnv)
  610. {
  611. long lRetVal = 0;
  612. WCHAR *pwc = (WCHAR *)pEnv;
  613. //count the variables
  614. while(*pwc){
  615. //get to end of variable
  616. while(*pwc){ pwc++; }
  617. pwc++;
  618. lRetVal++;
  619. }
  620. return lRetVal;
  621. }
  622. //Special Property Methods
  623. HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, WCHAR *wcValue, DWORD dwCount, ... )
  624. {
  625. if ( dwCount )
  626. {
  627. HRESULT hr = E_FAIL;
  628. CStringExt prop ( wcValue );
  629. va_list argList;
  630. va_start ( argList, dwCount );
  631. hr = prop.AppendList ( 0, NULL, dwCount, argList );
  632. va_end ( argList );
  633. if SUCCEEDED ( hr )
  634. {
  635. hr = PutProperty ( pObj, wcProperty, prop );
  636. }
  637. return hr;
  638. }
  639. else
  640. {
  641. return PutProperty ( pObj, wcProperty, wcValue );
  642. }
  643. }
  644. //Special Key Property Methods
  645. HRESULT CGenericClass::PutKeyProperty ( IWbemClassObject *pObj,
  646. const char *wcProperty,
  647. WCHAR *wcValue,
  648. bool *bKey,
  649. CRequestObject *pRequest,
  650. DWORD dwCount,
  651. ...
  652. )
  653. {
  654. if ( dwCount )
  655. {
  656. HRESULT hr = E_FAIL;
  657. CStringExt prop ( wcValue );
  658. va_list argList;
  659. va_start ( argList, dwCount );
  660. hr = prop.AppendList ( 0, NULL, dwCount, argList );
  661. va_end ( argList );
  662. if SUCCEEDED ( hr )
  663. {
  664. hr = PutKeyProperty ( pObj, wcProperty,prop, bKey, pRequest );
  665. }
  666. return hr;
  667. }
  668. else
  669. {
  670. return PutKeyProperty ( pObj, wcProperty, wcValue, bKey, pRequest );
  671. }
  672. }
  673. HRESULT CGenericClass::GetBufferNeccessary ( MSIHANDLE& handle,
  674. DWORD dwIndex,
  675. DWORD& dwSize,
  676. LPWSTR staticBuffer,
  677. BOOL bThrow
  678. )
  679. {
  680. HRESULT hResult = WBEM_S_NO_ERROR;
  681. UINT uiStatus = ERROR_SUCCESS;
  682. DWORD dwOldSize = dwSize;
  683. uiStatus = g_fpMsiRecordGetStringW ( handle, dwIndex, staticBuffer, &dwSize );
  684. if ( uiStatus != ERROR_SUCCESS )
  685. {
  686. if ( uiStatus == ERROR_MORE_DATA )
  687. {
  688. hResult = WBEM_S_FALSE;
  689. }
  690. else
  691. {
  692. if ( bThrow )
  693. {
  694. CheckMSI ( uiStatus );
  695. }
  696. else
  697. {
  698. hResult = ConvertError ( uiStatus );
  699. }
  700. }
  701. }
  702. else
  703. {
  704. if ( hResult == WBEM_S_NO_ERROR )
  705. {
  706. if ( dwOldSize < dwSize )
  707. {
  708. hResult = WBEM_S_FALSE;
  709. }
  710. }
  711. }
  712. return hResult;
  713. }
  714. HRESULT CGenericClass::GetBuffer ( MSIHANDLE& handle,
  715. DWORD dwIndex,
  716. DWORD& dwSize,
  717. DWORD& dwdynSize,
  718. LPWSTR& dynBuffer,
  719. BOOL bThrow
  720. )
  721. {
  722. HRESULT hResult = WBEM_S_NO_ERROR;
  723. UINT uiStatus = ERROR_SUCCESS;
  724. if ( dwSize )
  725. {
  726. if ( dwdynSize < dwSize )
  727. {
  728. if ( dynBuffer )
  729. {
  730. delete [] dynBuffer;
  731. dynBuffer = NULL;
  732. }
  733. if ( ( dynBuffer = new WCHAR [ dwSize + 1 ] ) != NULL )
  734. {
  735. dynBuffer [ 0 ] = 0;
  736. dwdynSize = dwSize;
  737. }
  738. else
  739. {
  740. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  741. }
  742. }
  743. DWORD dwOldSize = dwSize;
  744. try
  745. {
  746. uiStatus = g_fpMsiRecordGetStringW ( handle, dwIndex, dynBuffer, &dwSize );
  747. }
  748. catch ( ... )
  749. {
  750. if ( dynBuffer )
  751. {
  752. delete [] dynBuffer;
  753. dynBuffer = NULL;
  754. }
  755. dwdynSize = 0;
  756. throw;
  757. }
  758. if ( uiStatus != ERROR_SUCCESS )
  759. {
  760. BOOL bError = TRUE;
  761. if ( dynBuffer && dynBuffer [ 0 ] != 0 )
  762. {
  763. dynBuffer [ 0 ] = 0;
  764. }
  765. // strange MSI problem !
  766. //
  767. // allocated buffer with lenght as expected
  768. // buffer sent and ERROR_MORE_DATA was returned
  769. // unfortunately requested lenght is equal as previous !
  770. if ( uiStatus == ERROR_MORE_DATA )
  771. {
  772. if ( dwOldSize == dwSize )
  773. {
  774. bError = FALSE;
  775. }
  776. }
  777. if ( bError )
  778. {
  779. if ( dynBuffer )
  780. {
  781. delete [] dynBuffer;
  782. dynBuffer = NULL;
  783. }
  784. dwdynSize = 0L;
  785. if ( bThrow )
  786. {
  787. CheckMSI ( uiStatus );
  788. }
  789. else
  790. {
  791. hResult = ConvertError ( uiStatus );
  792. }
  793. }
  794. }
  795. }
  796. else
  797. {
  798. hResult = WBEM_E_INVALID_PARAMETER;
  799. }
  800. return hResult;
  801. }
  802. HRESULT CGenericClass::PutPropertySpecial ( MSIHANDLE& handle,
  803. DWORD dwIndex,
  804. DWORD& dwSize,
  805. LPWSTR staticBuffer,
  806. DWORD& dwdynSize,
  807. LPWSTR& dynBuffer,
  808. LPCSTR tszPropName,
  809. BOOL bThrow
  810. )
  811. {
  812. HRESULT hResult = WBEM_S_NO_ERROR;
  813. UINT uiStatus = ERROR_SUCCESS;
  814. if ( handle )
  815. {
  816. hResult = GetBufferNeccessary ( handle, dwIndex, dwSize, staticBuffer, bThrow );
  817. if SUCCEEDED ( hResult )
  818. {
  819. if ( hResult == WBEM_S_NO_ERROR )
  820. {
  821. hResult = PutProperty ( m_pObj, tszPropName, staticBuffer );
  822. }
  823. else
  824. if ( hResult == WBEM_S_FALSE )
  825. {
  826. try
  827. {
  828. hResult = GetBuffer ( handle, dwIndex, dwSize, dwdynSize, dynBuffer, bThrow );
  829. if SUCCEEDED ( hResult )
  830. {
  831. hResult = PutProperty ( m_pObj, tszPropName, dynBuffer );
  832. if ( dynBuffer && dynBuffer [ 0 ] != 0 )
  833. {
  834. dynBuffer [ 0 ] = 0;
  835. }
  836. }
  837. }
  838. catch ( ... )
  839. {
  840. if ( dynBuffer )
  841. {
  842. delete [] dynBuffer;
  843. dynBuffer = NULL;
  844. }
  845. dwdynSize = 0;
  846. throw;
  847. }
  848. }
  849. }
  850. }
  851. else
  852. {
  853. hResult = WBEM_E_INVALID_PARAMETER;
  854. }
  855. return hResult;
  856. }
  857. HRESULT CGenericClass::PutPropertySpecial ( MSIHANDLE& handle,
  858. DWORD dwIndex,
  859. DWORD& dwSize,
  860. LPWSTR staticBuffer,
  861. DWORD& dwdynSize,
  862. LPWSTR& dynBuffer,
  863. BOOL bThrow,
  864. DWORD dwCount,
  865. ...
  866. )
  867. {
  868. HRESULT hResult = WBEM_S_NO_ERROR;
  869. UINT uiStatus = ERROR_SUCCESS;
  870. if ( handle )
  871. {
  872. va_list argList;
  873. va_start ( argList, dwCount );
  874. LPCSTR tszPropName = NULL;
  875. try
  876. {
  877. hResult = GetBufferNeccessary ( handle, dwIndex, dwSize, staticBuffer, bThrow );
  878. if SUCCEEDED ( hResult )
  879. {
  880. if ( hResult == WBEM_S_NO_ERROR )
  881. {
  882. for ( DWORD dw = 0; (dw < dwCount) && (SUCCEEDED ( hResult )) ; dw++ )
  883. {
  884. if ( ( tszPropName = va_arg ( argList, LPCSTR ) ) != NULL )
  885. {
  886. hResult = PutProperty ( m_pObj, tszPropName, staticBuffer );
  887. ; }
  888. }
  889. }
  890. else
  891. if ( hResult == WBEM_S_FALSE )
  892. {
  893. try
  894. {
  895. hResult = GetBuffer ( handle, dwIndex, dwSize, dwdynSize, dynBuffer, bThrow );
  896. if SUCCEEDED ( hResult )
  897. {
  898. for ( DWORD dw = 0; (dw < dwCount) && (SUCCEEDED ( hResult )) ; dw++ )
  899. {
  900. if ( ( tszPropName = va_arg ( argList, LPCSTR ) ) != NULL )
  901. {
  902. hResult = PutProperty ( m_pObj, tszPropName, dynBuffer );
  903. }
  904. }
  905. if ( dynBuffer && dynBuffer [ 0 ] != 0 )
  906. {
  907. dynBuffer [ 0 ] = 0;
  908. }
  909. }
  910. }
  911. catch ( ... )
  912. {
  913. if ( dynBuffer )
  914. {
  915. delete [] dynBuffer;
  916. dynBuffer = NULL;
  917. }
  918. dwdynSize = 0;
  919. throw;
  920. }
  921. }
  922. }
  923. }
  924. catch ( ... )
  925. {
  926. va_end ( argList );
  927. throw;
  928. }
  929. va_end ( argList );
  930. }
  931. else
  932. {
  933. hResult = WBEM_E_INVALID_PARAMETER;
  934. }
  935. return hResult;
  936. }
  937. HRESULT CGenericClass::GetBufferToPut ( MSIHANDLE& handle,
  938. DWORD dwIndex,
  939. DWORD& dwSize,
  940. LPWSTR staticBuffer,
  941. DWORD& dwdynSize,
  942. LPWSTR& dynBuffer,
  943. LPWSTR& Buffer,
  944. BOOL bThrow
  945. )
  946. {
  947. HRESULT hResult = WBEM_S_NO_ERROR;
  948. UINT uiStatus = ERROR_SUCCESS;
  949. if ( handle )
  950. {
  951. hResult = GetBufferNeccessary ( handle, dwIndex, dwSize, staticBuffer, bThrow );
  952. if SUCCEEDED ( hResult )
  953. {
  954. if ( hResult == WBEM_S_NO_ERROR )
  955. {
  956. Buffer = staticBuffer;
  957. }
  958. else
  959. if ( hResult == WBEM_S_FALSE )
  960. {
  961. try
  962. {
  963. hResult = GetBuffer ( handle, dwIndex, dwSize, dwdynSize, dynBuffer, bThrow );
  964. if SUCCEEDED ( hResult )
  965. {
  966. Buffer = dynBuffer;
  967. }
  968. }
  969. catch ( ... )
  970. {
  971. if ( dynBuffer )
  972. {
  973. delete [] dynBuffer;
  974. dynBuffer = NULL;
  975. }
  976. dwdynSize = 0;
  977. Buffer = NULL;
  978. throw;
  979. }
  980. }
  981. }
  982. }
  983. else
  984. {
  985. hResult = WBEM_E_INVALID_PARAMETER;
  986. }
  987. return hResult;
  988. }