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.

1030 lines
24 KiB

  1. // RASrv.cpp : Implementation of CRASrv
  2. #include "stdafx.h"
  3. #include "Raserver.h"
  4. #include "RASrv.h"
  5. #include <ProjectConstants.h>
  6. #include <rcbdyctl.h>
  7. #include <rcbdyctl_i.c>
  8. #define SIZE_BUFF 256
  9. /*extern "C"
  10. {
  11. DWORD APIENTRY SquishAddress(WCHAR *szIp, WCHAR *szCompIp);
  12. DWORD APIENTRY ExpandAddress(WCHAR *szIp, WCHAR *szCompIp);
  13. };
  14. */
  15. // **** This code was in the ICSHelper
  16. /****************************************************************************
  17. **
  18. ** Address String Compression routines
  19. **
  20. *****************************************************************************
  21. **
  22. ** The following is a group of routines designed to compress and expand
  23. ** IPV4 addresses into the absolute minimum size possible. This is to
  24. ** provide a compressed ASCII string that can be parsed using standard
  25. ** shell routines for command line parsing.
  26. ** The compressed string has the following restrictions:
  27. ** -> Must not expand to more characters if UTF8 encoded.
  28. ** -> Must not contain the NULL character so that string libs work.
  29. ** -> Cannot contain double quote character, the shell needs that.
  30. ** -> Does not have to be human readable.
  31. **
  32. ** Data Types:
  33. ** There are three data types used here:
  34. ** szAddr The orginal IPV4 string address ("X.X.X.X:port")
  35. ** blobAddr Six byte struct with 4 bytes of address, and 2 bytes of port
  36. ** szComp Eight byte ascii string of compressed IPV4 address
  37. **
  38. ****************************************************************************/
  39. #define COMP_OFFSET '#'
  40. #define COMP_SEPERATOR '!'
  41. #pragma pack(push,1)
  42. typedef struct _BLOB_ADDR {
  43. UCHAR addr_d; // highest order address byte
  44. UCHAR addr_c;
  45. UCHAR addr_b;
  46. UCHAR addr_a; // lowest order byte (last in IP string address)
  47. WORD port;
  48. } BLOB_ADDR, *PBLOB_ADDR;
  49. #pragma pack(pop)
  50. WCHAR b64Char[64]={
  51. 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  52. 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
  53. '0','1','2','3','4','5','6','7','8','9','+','/'
  54. };
  55. /****************************************************************************
  56. ** char * atob(char *szVal, UCHAR *result)
  57. ****************************************************************************/
  58. WCHAR *atob(WCHAR *szVal, UCHAR *result)
  59. {
  60. WCHAR *lptr;
  61. WCHAR ucb;
  62. UCHAR foo;
  63. if (!result || !szVal)
  64. {
  65. OutputDebugString(L"ERROR: NULL ptr passed in atob");
  66. return NULL;
  67. }
  68. // start ptr at the beginning of string
  69. lptr = szVal;
  70. foo = 0;
  71. ucb = *lptr++ - '0';
  72. while (ucb >= 0 && ucb <= 9)
  73. {
  74. foo *= 10;
  75. foo += ucb;
  76. ucb = (*lptr++)-'0';
  77. }
  78. *result = (UCHAR)foo;
  79. return lptr;
  80. }
  81. /****************************************************************************
  82. **
  83. ** CompressAddr(pszAddr, pblobAddr);
  84. ** Takes an ascii IP address (X.X.X.X:port) and converts it to a
  85. ** 6 byte binary blob.
  86. **
  87. ** returns TRUE for success, FALSE for failure.
  88. **
  89. ****************************************************************************/
  90. BOOL CompressAddr(WCHAR *pszAddr, PBLOB_ADDR pblobAddr)
  91. {
  92. BLOB_ADDR lblob;
  93. WCHAR *lpsz;
  94. if (!pszAddr || !pblobAddr)
  95. {
  96. OutputDebugString(L"ERROR: NULL ptr passed in CompressAddr");
  97. return FALSE;
  98. }
  99. lpsz = pszAddr;
  100. lpsz = atob(lpsz, &lblob.addr_d);
  101. if (*(lpsz-1) != '.')
  102. {
  103. OutputDebugString(L"ERROR: bad address[0] passed in CompressAddr");
  104. return FALSE;
  105. }
  106. lpsz = atob(lpsz, &lblob.addr_c);
  107. if (*(lpsz-1) != '.')
  108. {
  109. OutputDebugString(L"ERROR: bad address[1] passed in CompressAddr");
  110. return FALSE;
  111. }
  112. lpsz = atob(lpsz, &lblob.addr_b);
  113. if (*(lpsz-1) != '.')
  114. {
  115. OutputDebugString(L"ERROR: bad address[2] passed in CompressAddr");
  116. return FALSE;
  117. }
  118. lpsz = atob(lpsz, &lblob.addr_a);
  119. // is there a port number here?
  120. if (*(lpsz-1) == ':')
  121. lblob.port = (WORD)_wtoi(lpsz);
  122. else
  123. lblob.port = 0;
  124. // copy back the result
  125. memcpy(pblobAddr, &lblob, sizeof(*pblobAddr));
  126. return TRUE;
  127. }
  128. /****************************************************************************
  129. **
  130. ** ExpandAddr(pszAddr, pblobAddr);
  131. ** Takes 6 byte binary blob and converts it into an ascii IP
  132. ** address (X.X.X.X:port)
  133. **
  134. ** returns TRUE for success, FALSE for failure.
  135. **
  136. ****************************************************************************/
  137. BOOL ExpandAddr(WCHAR *pszAddr, PBLOB_ADDR pba)
  138. {
  139. if (!pszAddr || !pba)
  140. {
  141. OutputDebugString(L"ERROR: NULL ptr passed in ExpandAddr");
  142. return FALSE;
  143. }
  144. wsprintf(pszAddr, L"%d.%d.%d.%d", pba->addr_d, pba->addr_c,
  145. pba->addr_b, pba->addr_a);
  146. if (pba->port)
  147. {
  148. WCHAR scratch[8];
  149. wsprintf(scratch, L":%d", pba->port);
  150. wcscat(pszAddr, scratch);
  151. }
  152. return TRUE;
  153. }
  154. /****************************************************************************
  155. **
  156. ** AsciifyAddr(pszAddr, pblobAddr);
  157. ** Takes 6 byte binary blob and converts it into compressed ascii
  158. ** will return either 6 or 8 bytes of string
  159. **
  160. ** returns TRUE for success, FALSE for failure.
  161. **
  162. ****************************************************************************/
  163. BOOL AsciifyAddr(WCHAR *pszAddr, PBLOB_ADDR pba)
  164. {
  165. UCHAR tmp;
  166. DWORDLONG dwl;
  167. int i, iCnt;
  168. if (!pszAddr || !pba)
  169. {
  170. OutputDebugString(L"ERROR: NULL ptr passed in AsciifyAddr");
  171. return FALSE;
  172. }
  173. iCnt = 6;
  174. if (pba->port)
  175. iCnt = 8;
  176. dwl = 0;
  177. memcpy(&dwl, pba, sizeof(*pba));
  178. for (i = 0; i < iCnt; i++)
  179. {
  180. // get 6 bits of data
  181. tmp = (UCHAR)(dwl & 0x3f);
  182. // add the offset to asciify this
  183. // offset must be bigger the double-quote char.
  184. pszAddr[i] = b64Char[tmp]; // (WCHAR)(tmp + COMP_OFFSET);
  185. // Shift right 6 bits
  186. dwl = Int64ShrlMod32(dwl, 6);
  187. }
  188. // terminating NULL
  189. pszAddr[iCnt] = 0;
  190. return TRUE;
  191. }
  192. /****************************************************************************
  193. **
  194. ** DeAsciifyAddr(pszAddr, pblobAddr);
  195. ** Takes a compressed ascii string and converts it into a
  196. ** 6 or 8 byte binary blob
  197. **
  198. ** returns TRUE for success, FALSE for failure.
  199. **
  200. ****************************************************************************/
  201. BOOL DeAsciifyAddr(WCHAR *pszAddr, PBLOB_ADDR pba)
  202. {
  203. UCHAR tmp;
  204. WCHAR wtmp;
  205. DWORDLONG dwl;
  206. int i;
  207. int iCnt;
  208. if (!pszAddr || !pba)
  209. {
  210. OutputDebugString(L"ERROR: NULL ptr passed in DeAsciifyAddr");
  211. return FALSE;
  212. }
  213. /* how long is this string?
  214. * if it is 6 bytes, then there is no port
  215. * else it should be 8 bytes
  216. */
  217. i = wcslen(pszAddr);
  218. if (i == 6 || i == 8)
  219. iCnt = i;
  220. else
  221. {
  222. iCnt = 8;
  223. OutputDebugString(L"Strlen is wrong in DeAsciifyAddr");
  224. }
  225. dwl = 0;
  226. for (i = iCnt-1; i >= 0; i--)
  227. {
  228. wtmp = pszAddr[i];
  229. if (wtmp >= L'A' && wtmp <= L'Z')
  230. tmp = wtmp - L'A';
  231. else if (wtmp >= L'a' && wtmp <= L'z')
  232. tmp = wtmp - L'a' + 26;
  233. else if (wtmp >= L'0' && wtmp <= L'9')
  234. tmp = wtmp - L'0' + 52;
  235. else if (wtmp == L'+')
  236. tmp = 62;
  237. else if (wtmp == L'/')
  238. tmp = 63;
  239. else
  240. {
  241. tmp = 0;
  242. OutputDebugString(L"ERROR:found invalid character in decode stream");
  243. }
  244. // tmp = (UCHAR)(pszAddr[i] - COMP_OFFSET);
  245. if (tmp > 63)
  246. {
  247. tmp = 0;
  248. OutputDebugString(L"ERROR:screwup in DeAsciify");
  249. }
  250. dwl = Int64ShllMod32(dwl, 6);
  251. dwl |= tmp;
  252. }
  253. memcpy(pba, &dwl, sizeof(*pba));
  254. return TRUE;
  255. }
  256. /****************************************************************************
  257. **
  258. ** SquishAddress(char *szIp, char *szCompIp)
  259. ** Takes one IP address and compresses it to minimum size
  260. **
  261. ****************************************************************************/
  262. DWORD APIENTRY SquishAddress(WCHAR *szIp, WCHAR *szCompIp)
  263. {
  264. WCHAR *thisAddr, *nextAddr;
  265. BLOB_ADDR ba;
  266. if (!szIp || !szCompIp)
  267. {
  268. OutputDebugString(L"SquishAddress called with NULL ptr");
  269. return ERROR_INVALID_PARAMETER;
  270. }
  271. // TRIVIAL_MSG((L"SquishAddress(%s)", szIp));
  272. thisAddr = szIp;
  273. szCompIp[0] = 0;
  274. while (thisAddr)
  275. {
  276. WCHAR scr[10];
  277. nextAddr = wcschr(thisAddr, L';');
  278. if (nextAddr && *(nextAddr+1))
  279. {
  280. *nextAddr = 0;
  281. }
  282. else
  283. nextAddr=0;
  284. CompressAddr(thisAddr, &ba);
  285. AsciifyAddr(scr, &ba);
  286. wcscat(szCompIp, scr);
  287. if (nextAddr)
  288. {
  289. // restore seperator found earlier
  290. *nextAddr = ';';
  291. nextAddr++;
  292. wcscat(szCompIp, L"!" /* COMP_SEPERATOR */);
  293. }
  294. thisAddr = nextAddr;
  295. }
  296. // TRIVIAL_MSG((L"SquishAddress returns [%s]", szCompIp));
  297. return ERROR_SUCCESS;
  298. }
  299. /****************************************************************************
  300. **
  301. ** ExpandAddress(char *szIp, char *szCompIp)
  302. ** Takes a compressed IP address and returns it to
  303. ** "normal"
  304. **
  305. ****************************************************************************/
  306. DWORD APIENTRY ExpandAddress(WCHAR *szIp, WCHAR *szCompIp)
  307. {
  308. BLOB_ADDR ba;
  309. WCHAR *thisAddr, *nextAddr;
  310. if (!szIp || !szCompIp)
  311. {
  312. OutputDebugString(L"ExpandAddress called with NULL ptr");
  313. return ERROR_INVALID_PARAMETER;
  314. }
  315. // TRIVIAL_MSG((L"ExpandAddress(%s)", szCompIp));
  316. thisAddr = szCompIp;
  317. szIp[0] = 0;
  318. while (thisAddr)
  319. {
  320. WCHAR scr[32];
  321. nextAddr = wcschr(thisAddr, COMP_SEPERATOR);
  322. if (nextAddr) *nextAddr = 0;
  323. DeAsciifyAddr(thisAddr, &ba);
  324. ExpandAddr(scr, &ba);
  325. wcscat(szIp, scr);
  326. if (nextAddr)
  327. {
  328. // restore seperator found earlier
  329. *nextAddr = COMP_SEPERATOR;
  330. nextAddr++;
  331. wcscat(szIp, L";");
  332. }
  333. thisAddr = nextAddr;
  334. }
  335. // TRIVIAL_MSG((L"ExpandAddress returns [%s]", szIp));
  336. return ERROR_SUCCESS;
  337. }
  338. // ***** END ICSHelper code
  339. bool CRASrv::InApprovedDomain()
  340. {
  341. // WCHAR ourUrl[INTERNET_MAX_URL_LENGTH];
  342. CComBSTR cbOurURL;
  343. if (!GetOurUrl(cbOurURL))
  344. {
  345. return false;
  346. }
  347. return IsApprovedDomain(cbOurURL);
  348. }
  349. bool CRASrv::GetOurUrl(CComBSTR & cbOurURL)
  350. {
  351. HRESULT hr;
  352. CComPtr<IServiceProvider> spSrvProv;
  353. CComPtr<IWebBrowser2> spWebBrowser;
  354. // Get site pointer...
  355. CComPtr<IOleClientSite> spClientSite;
  356. hr = GetClientSite((IOleClientSite**)&spClientSite);
  357. if (FAILED(hr))
  358. {
  359. return false;
  360. }
  361. hr = spClientSite->QueryInterface(IID_IServiceProvider, (void **)&spSrvProv);
  362. if (FAILED(hr))
  363. {
  364. return false;
  365. }
  366. hr = spSrvProv->QueryService(SID_SWebBrowserApp,
  367. IID_IWebBrowser2,
  368. (void**)&spWebBrowser);
  369. if (FAILED(hr))
  370. return false;
  371. CComBSTR bstrURL;
  372. if (FAILED(spWebBrowser->get_LocationURL(&bstrURL)))
  373. return false;
  374. cbOurURL = bstrURL.Copy();
  375. return true;
  376. }
  377. bool CRASrv::IsApprovedDomain(CComBSTR & cbOurURL)
  378. {
  379. // Only allow http access.
  380. // You can change this to allow file:// access.
  381. //
  382. INTERNET_SCHEME isResult;
  383. isResult = GetScheme(cbOurURL);
  384. if ( (isResult != INTERNET_SCHEME_HTTPS) )
  385. {
  386. return false;
  387. }
  388. //char ourDomain[256];
  389. CComBSTR cbOurDomain;
  390. CComBSTR cbGoodDomain[] = {L"www.microsoft.com",
  391. L"microsoft.com",
  392. L"microsoft"};
  393. if (!GetDomain(cbOurURL, cbOurDomain))
  394. return false;
  395. // Go through all the domains that should work
  396. if (MatchDomains(cbGoodDomain[0], cbOurDomain) ||
  397. MatchDomains(cbGoodDomain[1], cbOurDomain) ||
  398. MatchDomains(cbGoodDomain[2], cbOurDomain)
  399. )
  400. {
  401. return true;
  402. }
  403. return false;
  404. }
  405. INTERNET_SCHEME CRASrv::GetScheme(CComBSTR & cbUrl)
  406. {
  407. WCHAR buf[32];
  408. URL_COMPONENTS uc;
  409. ZeroMemory(&uc, sizeof uc);
  410. uc.dwStructSize = sizeof(uc);
  411. uc.lpszScheme = buf;
  412. uc.dwSchemeLength = sizeof buf;
  413. if (InternetCrackUrl(cbUrl, cbUrl.Length() , ICU_DECODE, &uc))
  414. return uc.nScheme;
  415. else
  416. return INTERNET_SCHEME_UNKNOWN;
  417. }
  418. bool CRASrv::GetDomain(CComBSTR & cbUrl, CComBSTR & cbBuf)
  419. {
  420. bool bRet = TRUE;
  421. URL_COMPONENTS uc;
  422. ZeroMemory(&uc, sizeof uc);
  423. WCHAR buf[INTERNET_MAX_URL_LENGTH];
  424. int cbBuff = sizeof(WCHAR) * INTERNET_MAX_URL_LENGTH;
  425. uc.dwStructSize = sizeof uc;
  426. uc.lpszHostName = buf;
  427. uc.dwHostNameLength = cbBuff;
  428. if (!InternetCrackUrl(cbUrl, cbUrl.Length(), ICU_DECODE, &uc))
  429. {
  430. bRet = FALSE;
  431. }
  432. else
  433. {
  434. cbBuf = buf;
  435. bRet = true;
  436. }
  437. return bRet;
  438. }
  439. // Return if ourDomain is within approvedDomain.
  440. // approvedDomain must either match ourDomain
  441. // or be a suffix preceded by a dot.
  442. //
  443. bool CRASrv::MatchDomains(CComBSTR& approvedDomain, CComBSTR& ourDomain)
  444. {
  445. /* int apDomLen = lstrlen(approvedDomain);
  446. int ourDomLen = lstrlen(ourDomain);
  447. if (apDomLen > ourDomLen)
  448. return false;
  449. if (lstrcmpi(ourDomain+ourDomLen-apDomLen, approvedDomain)
  450. != 0)
  451. return false;
  452. if (apDomLen == ourDomLen)
  453. return true;
  454. if (ourDomain[ourDomLen - apDomLen - 1] == '.')
  455. return true;
  456. */
  457. return approvedDomain == ourDomain ? true : false;
  458. }
  459. /////////////////////////////////////////////////////////////////////////////
  460. // CRASrv
  461. // CRAServer
  462. // Function: StartRA
  463. //
  464. // Parameter: BSTR strData - contains the following in a comma delimited string
  465. // <IPLIST>,<SessionID>,<PublicKey>
  466. STDMETHODIMP CRASrv::StartRA(BSTR strData, BSTR strPassword)
  467. {
  468. HRESULT hr = S_OK;
  469. STARTUPINFO StartUp;
  470. PROCESS_INFORMATION p_i;
  471. BOOL result;
  472. if ((strData == NULL) || (*strData == L'\0'))
  473. {
  474. hr = E_INVALIDARG;
  475. return hr;
  476. }
  477. if (strData[1] == NULL)
  478. {
  479. hr = E_INVALIDARG;
  480. return hr;
  481. }
  482. // Note, there is not always a strPassword so don't fail if it's NULL
  483. if (!InApprovedDomain())
  484. {
  485. hr = E_FAIL;
  486. return hr;
  487. }
  488. // **** Parse out the components of the string into CComBSTRs
  489. CComBSTR strIn; // Used as the local storage
  490. strIn = strData; // Copy the contents so that we can parse
  491. CComBSTR strVer;
  492. BOOL bPassword = FALSE;
  493. BOOL bModem = FALSE;
  494. CComBSTR strIPList;
  495. CComBSTR strSessionID;
  496. CComBSTR strPublicKey;
  497. WCHAR * tok;
  498. CComBSTR strSquishedIPList;
  499. CComBSTR strExpandedIPList;
  500. DWORD dwRet = 0x0;
  501. CComBSTR strExe( HC_ROOT_HELPSVC_BINARIES L"\\HelpCtr.exe" );
  502. WCHAR * pStr;
  503. int iSizeStr = 128;
  504. // Expand environment variables in strExe
  505. pStr = new WCHAR[iSizeStr];
  506. dwRet = ::ExpandEnvironmentStrings(strExe, pStr, iSizeStr);
  507. if (dwRet == 0)
  508. {
  509. return E_FAIL;
  510. }
  511. if (dwRet >= 128) // if the Buffer is too small
  512. {
  513. delete [] pStr;
  514. pStr = new WCHAR[dwRet];
  515. dwRet = ::ExpandEnvironmentStrings(strExe, pStr, dwRet);
  516. if (dwRet == 0)
  517. {
  518. return E_FAIL;
  519. }
  520. }
  521. // Copy the new expanded buffer back to strExe
  522. strExe = pStr;
  523. // Release the memory allocated to expand the Env Vars
  524. delete [] pStr;
  525. // Parse the BSTR (strIn) to get the ticket info.
  526. // Grab the lower byte of the first WCHAR and then get the squished IP List
  527. tok = ::wcstok(strIn, L",");
  528. if (tok != NULL)
  529. {
  530. // Check the password flag (bit 0)
  531. if (tok[0] & 0x1)
  532. bPassword = TRUE;
  533. else
  534. bPassword = FALSE;
  535. // Check the Modem flag (bit 1)
  536. if (tok[0] & 0x2)
  537. bModem = TRUE;
  538. else
  539. bModem = FALSE;
  540. tok = &tok[1]; // Move to the next WCHAR to start the Squished IPLIST
  541. strSquishedIPList = tok;
  542. }
  543. else
  544. {
  545. hr = ERROR_INVALID_USER_BUFFER;
  546. return hr;
  547. }
  548. tok = ::wcstok(NULL, L",");
  549. if (tok != NULL)
  550. {
  551. strSessionID = tok;
  552. }
  553. else
  554. {
  555. hr = ERROR_INVALID_USER_BUFFER;
  556. return hr;
  557. }
  558. tok = ::wcstok(NULL, L",");
  559. if (tok != NULL)
  560. {
  561. strPublicKey = tok;
  562. }
  563. else
  564. {
  565. hr = ERROR_INVALID_USER_BUFFER;
  566. return hr;
  567. }
  568. // Now convert the SquishedIPList to an ExpandedIPList
  569. WCHAR szIP[50];
  570. tok = ::wcstok(strSquishedIPList, L";");
  571. while (tok != NULL)
  572. {
  573. // Expand the current SquishedIP we are looking at
  574. ::ZeroMemory(szIP,sizeof(szIP));
  575. ::ExpandAddress(&szIP[0], (WCHAR*)tok);
  576. strExpandedIPList += szIP;
  577. // Grab Next Token
  578. tok = ::wcstok(NULL, L";");
  579. // add a ; at the end of each IP in the ExpandedIPList
  580. // ONLY if it's not the last IP in the list.
  581. if (tok != NULL)
  582. strExpandedIPList += L";";
  583. }
  584. strIPList = strExpandedIPList;
  585. // **** Create a temp file in the temp dir to store the ticket
  586. CComBSTR strTempPath;
  587. CComBSTR strTempFile;
  588. CComBSTR strPathFile; // Used as the full path and name of the file
  589. WCHAR buff[SIZE_BUFF];
  590. WCHAR buff2[SIZE_BUFF];
  591. // Clear out the memory in the buffer
  592. ZeroMemory(buff,sizeof(WCHAR)*SIZE_BUFF);
  593. if (!::GetTempPathW(SIZE_BUFF, (LPWSTR)&buff))
  594. {
  595. OutputDebugStringW(L"GetTempPath failed!\r\n");
  596. return E_FAIL;
  597. }
  598. strTempPath = buff;
  599. strTempPath += L"RA\\";
  600. // Create this directory
  601. if (!CreateDirectory((LPCWSTR)strTempPath, NULL))
  602. {
  603. if (ERROR_ALREADY_EXISTS != GetLastError())
  604. {
  605. OutputDebugStringW(L"CreateDirectory failed!\r\n");
  606. return E_FAIL;
  607. }
  608. }
  609. ZeroMemory(buff2,sizeof(WCHAR)*SIZE_BUFF);
  610. if (!::GetTempFileNameW((LPCWSTR)strTempPath, NULL, 0, (LPWSTR)&buff2))
  611. {
  612. OutputDebugStringW(L"GetTempFileName failed!\r\n");
  613. return E_FAIL;
  614. }
  615. strTempFile = buff2;
  616. // Write the ticket to the file
  617. CComBSTR strXMLTicket;
  618. strXMLTicket = L"<?xml version=\"1.0\" encoding=\"Unicode\" ?><UPLOADINFO TYPE=\"Escalated\"><UPLOADDATA RCTICKET=\"65538,1,";
  619. strXMLTicket += strIPList;
  620. strXMLTicket += L",";
  621. strXMLTicket += L"*assistantAccountPwd";
  622. strXMLTicket += L",";
  623. strXMLTicket += strSessionID;
  624. strXMLTicket += L",";
  625. strXMLTicket += L"*SolicitedHelp";
  626. strXMLTicket += L",";
  627. strXMLTicket += L"*helpSessionName";
  628. strXMLTicket += L",";
  629. strXMLTicket += strPublicKey;
  630. strXMLTicket += L"\" ";
  631. strXMLTicket += L"RCTICKETENCRYPTED=\"";
  632. strXMLTicket += (bPassword ? L"1\"" : L"0\"");
  633. strXMLTicket += L" L=";
  634. strXMLTicket += (bModem ? L"\"1\" " : L"\"0\" ");
  635. //strXMLTicket += L"DeleteTicket=\"1\" ";
  636. if (!bPassword)
  637. {
  638. strXMLTicket += L"URA=\"1\" ";
  639. }
  640. else
  641. {
  642. strXMLTicket += L"PassStub=\"";
  643. strXMLTicket += strSessionID;
  644. strXMLTicket += L"\" ";
  645. }
  646. strXMLTicket += "/></UPLOADINFO>";
  647. DWORD dwWritten = 0x0;
  648. // Create XML File for the incident
  649. CComPtr<IXMLDOMDocument> spXMLDoc;
  650. VARIANT_BOOL vbSuccess;
  651. CComVariant cvStrTempFile;
  652. hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&spXMLDoc);
  653. if (FAILED(hr))
  654. {
  655. return hr;
  656. }
  657. hr = spXMLDoc->loadXML(strXMLTicket, &vbSuccess);
  658. if (FAILED(hr) || (vbSuccess == VARIANT_FALSE))
  659. {
  660. return E_FAIL;
  661. }
  662. cvStrTempFile = strTempFile;
  663. hr = spXMLDoc->save(cvStrTempFile);
  664. if (FAILED(hr))
  665. {
  666. return hr;
  667. }
  668. // Start helpctr.exe with this ticket in order to start Remote Assistance
  669. // as an Expert
  670. strExe += L" -Mode \"hcp://system/Remote Assistance/RAHelpeeAcceptLayout.xml\" -url \"hcp://system/Remote Assistance/Interaction/Client/RcToolscreen1.htm\" -ExtraArgument \"IncidentFile=";
  671. strExe += strTempFile;
  672. strExe += L"\"";
  673. // initialize our structs
  674. ZeroMemory(&p_i, sizeof(p_i));
  675. ZeroMemory(&StartUp, sizeof(StartUp));
  676. StartUp.cb = sizeof(StartUp);
  677. StartUp.dwFlags = STARTF_USESHOWWINDOW;
  678. StartUp.wShowWindow = SW_SHOWNORMAL;
  679. result = CreateProcess(NULL, strExe,
  680. NULL, NULL, TRUE,
  681. NORMAL_PRIORITY_CLASS + CREATE_UNICODE_ENVIRONMENT ,
  682. NULL, // Environment block (must use the CREATE_UNICODE_ENVIRONMENT flag)
  683. NULL, &StartUp, &p_i);
  684. if (!result)
  685. {
  686. // CreateProcess Failed!
  687. dwRet = GetLastError();
  688. OutputDebugStringW(L"CreateProcessW failed!");
  689. return E_FAIL;
  690. }
  691. return hr;
  692. }
  693. /*
  694. STDMETHODIMP CRASrv::QueryOS(long *pRes)
  695. {
  696. OSVERSIONINFOEX osinfo;
  697. HRESULT hr = S_OK;
  698. if (!pRes)
  699. {
  700. hr = E_INVALIDARG;
  701. return hr;
  702. }
  703. memset((OSVERSIONINFO *)&osinfo, 0, sizeof(osinfo));
  704. osinfo.dwOSVersionInfoSize = sizeof(osinfo);
  705. if (!GetVersionEx((OSVERSIONINFO *)&osinfo))
  706. {
  707. return E_FAIL;
  708. }
  709. // Return the correct value
  710. // Operating System Constant
  711. // Windows XP 0x01
  712. // Windows 2000 0x02
  713. // Windows NT 0x03
  714. // Windows ME 0x04
  715. // Windows 98 0x05
  716. // Windows 95 0x06
  717. // Windows 3.x 0x07
  718. // Other 0x10
  719. switch(osinfo.dwMajorVersion)
  720. {
  721. case 5:
  722. switch(osinfo.dwMinorVersion)
  723. {
  724. case 1:
  725. *pRes = 0x01;
  726. break;
  727. case 0:
  728. *pRes = 0x02;
  729. break;
  730. default:
  731. // Nothing
  732. break;
  733. }
  734. break;
  735. case 4:
  736. switch(osinfo.dwMinorVersion)
  737. {
  738. case 0:
  739. // Win95 or NT 4
  740. *pRes = 0x03;
  741. break;
  742. case 10:
  743. // Win98
  744. *pRes = 0x05;
  745. break;
  746. case 90:
  747. //WinME
  748. *pRes = 0x04;
  749. break;
  750. default:
  751. // Nothing
  752. break;
  753. }
  754. break;
  755. case 3:
  756. //WinNT3.51
  757. *pRes = 0x07;
  758. default:
  759. *pRes = 0x10;
  760. break;
  761. }
  762. return hr ;
  763. }
  764. */
  765. //
  766. // Function: Cleanup()
  767. //
  768. // Description:
  769. //
  770. // This function goes into the RA temporary files directory
  771. // and cleans up all the files that are older than 5 minutes.
  772. bool CRASrv::Cleanup()
  773. {
  774. bool bRet = TRUE;
  775. WCHAR buff[SIZE_BUFF];
  776. CComBSTR strTempDir,
  777. strTempDirWild;
  778. CComBSTR strTempFile;
  779. HANDLE hFile;
  780. // *** Find out what the temp directory is
  781. // Clear out the memory in the buffer
  782. ZeroMemory(buff,sizeof(WCHAR)*SIZE_BUFF);
  783. if (!::GetTempPathW(SIZE_BUFF, (LPWSTR)&buff))
  784. {
  785. OutputDebugStringW(L"GetTempPath failed!\r\n");
  786. return false;
  787. }
  788. strTempDir = buff;
  789. strTempDir += L"RA\\";
  790. strTempDirWild = strTempDir;
  791. strTempDirWild += L"*.*";
  792. WIN32_FIND_DATA ffd;
  793. // then enumerate all the files in this directory
  794. hFile = ::FindFirstFileW((LPCWSTR)strTempDirWild, &ffd);
  795. if (hFile != INVALID_HANDLE_VALUE)
  796. {
  797. bool bCont = true;
  798. FILETIME ftSystemTime;
  799. SYSTEMTIME st;
  800. ::GetSystemTime(&st);
  801. ::SystemTimeToFileTime(&st, &ftSystemTime);
  802. int iTimeDelta,
  803. iTimeThreshold = 0x1; // The threshold is dec(0x1 0000 0000)*(1/60)*10^-9
  804. // which is approximately 7-8 minutes
  805. while (bCont)
  806. {
  807. // get the timestamp on this file if it's not . or ..
  808. if (!(
  809. (::wcscmp(L".", ffd.cFileName) == 0) ||
  810. (::wcscmp(L"..", ffd.cFileName) == 0)
  811. )
  812. )
  813. {
  814. iTimeDelta = ftSystemTime.dwHighDateTime - ffd.ftCreationTime.dwHighDateTime;
  815. if (iTimeDelta > iTimeThreshold)
  816. {
  817. // The file is older than the threshold, delete the file
  818. strTempFile = strTempDir;
  819. strTempFile += ffd.cFileName;
  820. ::DeleteFileW((LPCWSTR)strTempFile);
  821. }
  822. }
  823. // Grab the next file
  824. if (!::FindNextFileW(hFile, &ffd))
  825. {
  826. if (ERROR_NO_MORE_FILES == GetLastError())
  827. {
  828. bCont = false;
  829. }
  830. }
  831. }
  832. }
  833. return bRet;
  834. }