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.

1108 lines
22 KiB

  1. /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. utils.cxx
  5. Abstract:
  6. Utility functions.
  7. Author:
  8. Paul M Midgen (pmidge) 12-October-2000
  9. Revision History:
  10. 12-October-2000 pmidge
  11. Created
  12. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/
  13. #include "common.h"
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. const IID IID_IWinHttpRequest =
  18. {
  19. 0x06f29373,
  20. 0x5c5a,
  21. 0x4b54,
  22. {0xb0,0x25,0x6e,0xf1,0xbf,0x8a,0xbf,0x0e}
  23. };
  24. #ifdef __cplusplus
  25. }
  26. #endif
  27. //-----------------------------------------------------------------------------
  28. // file retrieval
  29. //-----------------------------------------------------------------------------
  30. BOOL
  31. __PathIsUNC(LPCWSTR path)
  32. {
  33. BOOL bIsUNC = FALSE;
  34. WCHAR* embedded = NULL;
  35. // is the path a UNC share? e.g. \\foo\bar\baz.htm
  36. if( wcsstr(path, L"\\\\") )
  37. {
  38. embedded = wcsstr(path, L"\\");
  39. if( embedded && (wcslen(embedded) > 1) )
  40. {
  41. bIsUNC = TRUE;
  42. }
  43. }
  44. else // how about a filesystem path, e.g. z:\foo\bar.htm
  45. {
  46. embedded = wcsstr(path, L":");
  47. if( embedded && ((embedded-1) == path) )
  48. {
  49. bIsUNC = TRUE;
  50. }
  51. }
  52. return bIsUNC;
  53. }
  54. BOOL
  55. __PathIsURL(LPCWSTR path)
  56. {
  57. BOOL bIsURL = FALSE;
  58. if( wcsstr(path, L"http") )
  59. {
  60. bIsURL = TRUE;
  61. }
  62. return bIsURL;
  63. }
  64. BOOL
  65. GetFile(LPCWSTR path, HANDLE* phUNC, IWinHttpRequest** ppWHR, DWORD mode, BOOL* bReadOnly)
  66. {
  67. DEBUG_ENTER((
  68. DBG_UTILS,
  69. rt_bool,
  70. "GetFile",
  71. "path=%S; phUNC=%#x; ppWHR=%#x; mode=%#x; bReadOnly=%#x",
  72. path,
  73. phUNC,
  74. ppWHR,
  75. mode,
  76. bReadOnly
  77. ));
  78. BOOL bSuccess = FALSE;
  79. if( path )
  80. {
  81. if( phUNC )
  82. {
  83. *phUNC = __OpenFile(path, mode, bReadOnly);
  84. if( *phUNC != INVALID_HANDLE_VALUE )
  85. {
  86. bSuccess = TRUE;
  87. }
  88. }
  89. else if( ppWHR )
  90. {
  91. *ppWHR = __OpenUrl(path);
  92. if( *ppWHR )
  93. {
  94. *bReadOnly = TRUE;
  95. bSuccess = TRUE;
  96. }
  97. }
  98. }
  99. DEBUG_LEAVE(bSuccess);
  100. return bSuccess;
  101. }
  102. HANDLE
  103. __OpenFile(LPCWSTR path, DWORD mode, BOOL* bReadOnly)
  104. {
  105. HANDLE hFile = INVALID_HANDLE_VALUE;
  106. DWORD flags = GENERIC_READ | GENERIC_WRITE;
  107. retry:
  108. hFile = CreateFile(
  109. path,
  110. flags,
  111. FILE_SHARE_READ,
  112. NULL,
  113. mode,
  114. FILE_ATTRIBUTE_NORMAL,
  115. NULL
  116. );
  117. if( hFile == INVALID_HANDLE_VALUE )
  118. {
  119. if( GetLastError() == ERROR_ACCESS_DENIED )
  120. {
  121. if( flags == (GENERIC_READ | GENERIC_WRITE) )
  122. {
  123. DEBUG_TRACE(UTILS, ("read/write open attempt failed, retrying for read-only access"));
  124. flags = GENERIC_READ;
  125. *bReadOnly = TRUE;
  126. goto retry;
  127. }
  128. }
  129. DEBUG_TRACE(UTILS, ("error opening %S: %s", path, MapErrorToString(GetLastError())));
  130. }
  131. else
  132. {
  133. DEBUG_TRACE(UTILS, ("file opened"));
  134. }
  135. return hFile;
  136. }
  137. IWinHttpRequest*
  138. __OpenUrl(LPCWSTR url)
  139. {
  140. HRESULT hr = S_OK;
  141. IWinHttpRequest* pWHR = NULL;
  142. BSTR bstrVerb = SysAllocString(L"GET");
  143. BSTR bstrUrl = SysAllocString(url);
  144. LONG status = 0L;
  145. CLSID clsid;
  146. NEWVARIANT(var);
  147. NEWVARIANT(async);
  148. V_VT(&async) = VT_BOOL;
  149. V_BOOL(&async) = FALSE;
  150. hr = CLSIDFromProgID(L"WinHttp.WinHttpRequest.5", &clsid);
  151. if( FAILED(hr) )
  152. {
  153. DEBUG_TRACE(UTILS, ("failed to get WinHttpRequest CLSID from registry (%s)", MapHResultToString(hr)));
  154. goto quit;
  155. }
  156. hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IWinHttpRequest, (void**) &pWHR);
  157. if( FAILED(hr) )
  158. {
  159. DEBUG_TRACE(UTILS, ("CoCreateInstance for IID_IWinHttpRequest failed (%s)", MapHResultToString(hr)));
  160. goto quit;
  161. }
  162. hr = pWHR->SetProxy(HTTPREQUEST_PROXYSETTING_PRECONFIG, var, var);
  163. if( FAILED(hr) )
  164. {
  165. DEBUG_TRACE(UTILS, ("failed to set proxy (%s)", MapHResultToString(hr)));
  166. goto quit;
  167. }
  168. hr = pWHR->Open(bstrVerb, bstrUrl, async);
  169. if( FAILED(hr) )
  170. {
  171. DEBUG_TRACE(UTILS, ("failed to open %S (%s)", bstrUrl, MapHResultToString(hr)));
  172. goto quit;
  173. }
  174. hr = pWHR->Send(var);
  175. if( FAILED(hr) )
  176. {
  177. DEBUG_TRACE(UTILS, ("failed to send request (%s)", MapHResultToString(hr)));
  178. goto quit;
  179. }
  180. hr = pWHR->get_Status(&status);
  181. if( SUCCEEDED(hr) )
  182. {
  183. DEBUG_TRACE(UTILS, ("response status %d", status));
  184. hr = (status == 200) ? S_OK : E_FAIL;
  185. }
  186. else
  187. {
  188. DEBUG_TRACE(UTILS, ("failed to get response status (%s)", MapHResultToString(hr)));
  189. }
  190. quit:
  191. if( FAILED(hr) )
  192. {
  193. SAFERELEASE(pWHR);
  194. }
  195. SAFEDELETEBSTR(bstrVerb);
  196. SAFEDELETEBSTR(bstrUrl);
  197. VariantClear(&var);
  198. VariantClear(&async);
  199. return pWHR;
  200. }
  201. //-----------------------------------------------------------------------------
  202. // general utility functions
  203. //-----------------------------------------------------------------------------
  204. HRESULT
  205. GetTypeInfoFromName(LPCOLESTR name, ITypeLib* ptl, ITypeInfo** ppti)
  206. {
  207. DEBUG_ENTER((
  208. DBG_UTILS,
  209. rt_hresult,
  210. "GetTypeInfoFromName",
  211. "name=%.16S; ptl=%#x; ppti=%#x",
  212. name,
  213. ptl,
  214. ppti
  215. ));
  216. HRESULT hr = S_OK;
  217. BOOL bFound = FALSE;
  218. USHORT cf = 1L;
  219. ULONG hash = 0L;
  220. LONG id = 0L;
  221. LPOLESTR pstr = NULL;
  222. if( !name || ! ptl )
  223. {
  224. hr = E_INVALIDARG;
  225. goto quit;
  226. }
  227. if( !ppti )
  228. {
  229. hr = E_POINTER;
  230. goto quit;
  231. }
  232. *ppti = NULL;
  233. pstr = __wstrdup(name);
  234. ptl->IsName(pstr, 0L, &bFound);
  235. if( !bFound )
  236. {
  237. hr = TYPE_E_ELEMENTNOTFOUND;
  238. goto quit;
  239. }
  240. hash = LHashValOfNameSys(
  241. SYS_WIN32,
  242. MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT),
  243. pstr
  244. );
  245. hr = ptl->FindName(pstr, hash, ppti, &id, &cf);
  246. DEBUG_TRACE(UTILS, ("find name: pti=%#x; cf=%d", *ppti, cf));
  247. quit:
  248. SAFEDELETEBUF(pstr);
  249. DEBUG_LEAVE(hr);
  250. return hr;
  251. }
  252. BOOL
  253. GetJScriptCLSID(LPCLSID pclsid)
  254. {
  255. DEBUG_ENTER((
  256. DBG_UTILS,
  257. rt_bool,
  258. "GetJScriptCLSID",
  259. "pclsid=%#x",
  260. pclsid
  261. ));
  262. BOOL ret = FALSE;
  263. HKEY hk = NULL;
  264. LPBYTE buf = NULL;
  265. DWORD cb = 0L;
  266. DWORD rt = REG_SZ;
  267. if( RegOpenKey(HKEY_CLASSES_ROOT, L"JScript\\CLSID", &hk) == ERROR_SUCCESS )
  268. {
  269. if( RegQueryValueEx(hk, L"", NULL, &rt, NULL, &cb) == ERROR_SUCCESS )
  270. {
  271. buf = new BYTE[cb];
  272. RegQueryValueEx(hk, L"", NULL, &rt, buf, &cb);
  273. CLSIDFromString((LPOLESTR) buf, pclsid);
  274. ret = TRUE;
  275. SAFEDELETEBUF(buf);
  276. }
  277. }
  278. DEBUG_LEAVE(ret);
  279. return ret;
  280. }
  281. void
  282. ParseSocketInfo(PIOCTX pi)
  283. {
  284. PSOCKADDR_IN pLocal = NULL;
  285. PSOCKADDR_IN pRemote = NULL;
  286. int cbLocal = 0;
  287. int cbRemote = 0;
  288. char* buf = NULL;
  289. int len = 0;
  290. int error = 0;
  291. GetAcceptExSockaddrs(
  292. pi->sockbuf, 0,
  293. SOCKADDRBUFSIZE,
  294. SOCKADDRBUFSIZE,
  295. (PSOCKADDR*) &pLocal, &cbLocal,
  296. (PSOCKADDR*) &pRemote, &cbRemote
  297. );
  298. pi->local = new HOSTINFO;
  299. pi->remote = new HOSTINFO;
  300. GetHostname(pLocal->sin_addr, &pi->local->name);
  301. pi->local->addr = __strdup(inet_ntoa(pLocal->sin_addr));
  302. pi->local->port = ntohs(pLocal->sin_port);
  303. GetHostname(pRemote->sin_addr, &pi->remote->name);
  304. pi->remote->addr = __strdup(inet_ntoa(pRemote->sin_addr));
  305. pi->remote->port = ntohs(pRemote->sin_port);
  306. if( !pi->remote->name )
  307. {
  308. pi->remote->name = __strdup(pi->remote->addr);
  309. }
  310. len = strlen(pi->remote->name)+7; // ":" plus 5 port digits and a null
  311. buf = new char[len];
  312. strncpy(buf, pi->remote->name, len);
  313. strncat(buf, ":", sizeof(char));
  314. _itoa(pi->remote->port, (buf+strlen(buf)), 10);
  315. pi->clientid = __ansitowide(buf);
  316. SAFEDELETEBUF(buf);
  317. }
  318. void
  319. GetHostname(struct in_addr ip, LPSTR* ppsz)
  320. {
  321. HOSTENT* ph = NULL;
  322. ph = gethostbyaddr(
  323. (char*) &ip,
  324. sizeof(struct in_addr),
  325. AF_INET
  326. );
  327. if( ph )
  328. {
  329. *ppsz = __strdup(ph->h_name);
  330. }
  331. else
  332. {
  333. *ppsz = NULL;
  334. }
  335. }
  336. DISPID
  337. GetDispidFromName(PDISPIDTABLEENTRY pdt, DWORD cEntries, LPWSTR name)
  338. {
  339. DWORD n = 0L;
  340. DWORD hash = GetHash(name);
  341. DISPID dispid = DISPID_UNKNOWN;
  342. while( n < cEntries )
  343. {
  344. if( pdt[n].hash != hash )
  345. {
  346. ++n;
  347. }
  348. else
  349. {
  350. dispid = pdt[n].dispid;
  351. break;
  352. }
  353. }
  354. DEBUG_TRACE(DISPATCH, ("hash %#x is %s", hash, MapDispidToString(dispid)));
  355. return dispid;
  356. }
  357. void
  358. AddRichErrorInfo(EXCEPINFO* pei, LPWSTR source, LPWSTR description, HRESULT error)
  359. {
  360. if( pei )
  361. {
  362. pei->bstrSource = __widetobstr((source ? source : L"unknown source"));
  363. pei->bstrDescription = __widetobstr((description ? description : L"no description"));
  364. pei->scode = error;
  365. }
  366. }
  367. DWORD
  368. GetHash(LPWSTR name)
  369. {
  370. DWORD hash = 0L;
  371. DWORD n = 0L;
  372. DWORD len = 0L;
  373. LPSTR string = NULL;
  374. string = __widetoansi(name);
  375. if( string )
  376. {
  377. _strlwr(string);
  378. for(n=0, len=strlen(string); n<=len; n++)
  379. {
  380. hash += __toascii(string[len-n]) * ((10<<n)^n);
  381. }
  382. DEBUG_TRACE(DISPATCH, ("name=%s; hash=%#x", string, hash));
  383. }
  384. SAFEDELETEBUF(string);
  385. return hash;
  386. }
  387. DWORD
  388. GetHash(LPSTR name)
  389. {
  390. DWORD hash = 0L;
  391. DWORD n = 0L;
  392. DWORD len = 0L;
  393. LPSTR string = NULL;
  394. string = __strdup(name);
  395. if( string )
  396. {
  397. _strlwr(string);
  398. for(n=0, len=strlen(string); n<=len; n++)
  399. {
  400. hash += __toascii(string[len-n]) * ((10<<n)^n);
  401. }
  402. DEBUG_TRACE(DISPATCH, ("name=%s; hash=%#x", string, hash));
  403. }
  404. SAFEDELETEBUF(string);
  405. return hash;
  406. }
  407. HRESULT
  408. ProcessVariant(VARIANT* pvar, LPBYTE* ppbuf, LPDWORD pcbuf, LPDWORD pbytes)
  409. {
  410. DEBUG_ENTER((
  411. DBG_UTILS,
  412. rt_hresult,
  413. "ProcessVariant",
  414. "pvar=%#x; ppbuf=%#x; pcbuf=%#x; pbytes=%#x",
  415. pvar,
  416. ppbuf,
  417. pcbuf,
  418. pbytes
  419. ));
  420. HRESULT hr = S_OK;
  421. LPBYTE pbyte = NULL;
  422. DWORD len = NULL;
  423. BOOL bAlloc = FALSE;
  424. BOOL bBypass = FALSE;
  425. if( !ppbuf || !pcbuf )
  426. {
  427. hr = E_INVALIDARG;
  428. goto quit;
  429. }
  430. //
  431. // if the caller wants us to allocate storage, we don't need
  432. // the pbytes parameter. otherwise, we do in case the caller
  433. // needs to resize their buffer.
  434. //
  435. if( ((*ppbuf) && *pcbuf != 0) && !pbytes )
  436. {
  437. hr = E_INVALIDARG;
  438. goto quit;
  439. }
  440. if( !(*ppbuf) && *pcbuf == 0 )
  441. {
  442. DEBUG_TRACE(UTILS, ("will allocate storage for variant data"));
  443. bAlloc = TRUE;
  444. }
  445. DEBUG_TRACE(
  446. RUNTIME,
  447. ("variant type is %s", MapVariantTypeToString(pvar))
  448. );
  449. switch( V_VT(pvar) )
  450. {
  451. case VT_BSTR :
  452. {
  453. pbyte = (LPBYTE) __widetoansi(V_BSTR(pvar));
  454. len = strlen((LPSTR) pbyte);
  455. }
  456. break;
  457. case VT_ARRAY | VT_UI1 :
  458. {
  459. SAFEARRAY* psa = V_ARRAY(pvar);
  460. LPBYTE ptmp = NULL;
  461. hr = SafeArrayAccessData(psa, (void**) &ptmp);
  462. if( SUCCEEDED(hr) )
  463. {
  464. SafeArrayGetUBound(psa, 1, (long*) &len);
  465. pbyte = new BYTE[len];
  466. memcpy(pbyte, ptmp, len);
  467. SafeArrayUnaccessData(psa);
  468. }
  469. }
  470. break;
  471. case VT_UNKNOWN :
  472. {
  473. hr = ProcessObject(pvar->punkVal, ppbuf, pcbuf, pbytes);
  474. bBypass = TRUE;
  475. }
  476. break;
  477. case VT_DISPATCH :
  478. {
  479. IUnknown* punk = NULL;
  480. if( SUCCEEDED(pvar->pdispVal->QueryInterface(IID_IUnknown, (void**) &punk)) )
  481. {
  482. hr = ProcessObject(punk, ppbuf, pcbuf, pbytes);
  483. bBypass = TRUE;
  484. }
  485. SAFERELEASE(punk);
  486. }
  487. break;
  488. default :
  489. {
  490. hr = E_INVALIDARG;
  491. }
  492. }
  493. //
  494. // bBypass is set when we make a call into ProcessObject(), which
  495. // always calls back into us to handle the unpacked non-object-type
  496. // variant. in that nested call the buffers & length variables are
  497. // set, so we bypass those operations when the outer call unwinds.
  498. //
  499. if( SUCCEEDED(hr) && !bBypass )
  500. {
  501. if( bAlloc )
  502. {
  503. *ppbuf = pbyte;
  504. *pcbuf = len;
  505. }
  506. else
  507. {
  508. if( *pcbuf >= len )
  509. {
  510. memcpy(*ppbuf, pbyte, len);
  511. *pbytes = len;
  512. }
  513. else
  514. {
  515. hr = E_OUTOFMEMORY;
  516. *pcbuf = len;
  517. }
  518. SAFEDELETEBUF(pbyte);
  519. }
  520. }
  521. quit:
  522. DEBUG_LEAVE(hr);
  523. return hr;
  524. }
  525. //
  526. // WARNING: do not modify these values. use disphash.exe to generate
  527. // new values.
  528. //
  529. #define CLASS_HASH_URL 0x0000417f
  530. #define CLASS_HASH_ENTITY 0x000213d4
  531. #define CLASS_HASH_HEADERS 0x000401cd
  532. HRESULT
  533. ProcessObject(IUnknown* punk, LPBYTE* ppbuf, LPDWORD pcbuf, LPDWORD pbytes)
  534. {
  535. DEBUG_ENTER((
  536. DBG_UTILS,
  537. rt_hresult,
  538. "ProcessObject",
  539. "punk=%#x",
  540. punk
  541. ));
  542. HRESULT hr = E_FAIL;
  543. IProvideClassInfo* pci = NULL;
  544. IW3SpoofFile* pfile = NULL;
  545. // first try to use class information to determine what was
  546. // passed in. all om objects support this method.
  547. //
  548. // BUGBUG: potential failure case is when objects are "torn off" from
  549. // their parents (e.g. persisted through the runtime property bag).
  550. // in that scenario the objects lose site information and therefore
  551. // aren't able to look up their typeinfo. fix is to cache typeinfo
  552. // during object creation.
  553. //
  554. // workitem filed IEv6 #21277
  555. //
  556. hr = punk->QueryInterface(IID_IProvideClassInfo, (void**) &pci);
  557. if( SUCCEEDED(hr) )
  558. {
  559. ITypeInfo* pti = NULL;
  560. IEntity* pentity = NULL;
  561. IHeaders* pheaders = NULL;
  562. IUrl* purl = NULL;
  563. BSTR name = NULL;
  564. NEWVARIANT(tmp);
  565. if( SUCCEEDED(pci->GetClassInfo(&pti)) )
  566. {
  567. pti->GetDocumentation(MEMBERID_NIL, &name, NULL, NULL, NULL);
  568. DEBUG_TRACE(SOCKET, ("processing an %S object", name));
  569. switch( GetHash(name) )
  570. {
  571. case CLASS_HASH_URL :
  572. {
  573. if( SUCCEEDED(punk->QueryInterface(IID_IUrl, (void**) &purl)) )
  574. {
  575. if( SUCCEEDED(purl->Get(&V_BSTR(&tmp))) )
  576. {
  577. V_VT(&tmp) = VT_BSTR;
  578. hr = ProcessVariant(&tmp, ppbuf, pcbuf, pbytes);
  579. }
  580. }
  581. }
  582. break;
  583. case CLASS_HASH_HEADERS :
  584. {
  585. if( SUCCEEDED(punk->QueryInterface(IID_IHeaders, (void**) &pheaders)) )
  586. {
  587. if( SUCCEEDED(pheaders->Get(&V_BSTR(&tmp))) )
  588. {
  589. V_VT(&tmp) = VT_BSTR;
  590. hr = ProcessVariant(&tmp, ppbuf, pcbuf, pbytes);
  591. }
  592. }
  593. }
  594. break;
  595. case CLASS_HASH_ENTITY :
  596. {
  597. if( SUCCEEDED(punk->QueryInterface(IID_IEntity, (void**) &pentity)) )
  598. {
  599. if( SUCCEEDED(pentity->Get(&tmp)) )
  600. {
  601. hr = ProcessVariant(&tmp, ppbuf, pcbuf, pbytes);
  602. }
  603. }
  604. }
  605. break;
  606. }
  607. SAFERELEASE(pti);
  608. SAFERELEASE(purl);
  609. SAFERELEASE(pentity);
  610. SAFERELEASE(pheaders);
  611. SAFEDELETEBSTR(name);
  612. VariantClear(&tmp);
  613. }
  614. SAFERELEASE(pci);
  615. if( SUCCEEDED(hr) )
  616. {
  617. goto quit;
  618. }
  619. }
  620. // try IW3SpoofFile...
  621. hr = punk->QueryInterface(IID_IW3SpoofFile, (void**) &pfile);
  622. if( SUCCEEDED(hr) )
  623. {
  624. NEWVARIANT(tmp);
  625. DEBUG_TRACE(SOCKET, ("processing an IW3SpoofFile object"));
  626. hr = pfile->ReadAll(&tmp);
  627. if( SUCCEEDED(hr) )
  628. {
  629. hr = ProcessVariant(&tmp, ppbuf, pcbuf, pbytes);
  630. }
  631. SAFERELEASE(pfile);
  632. VariantClear(&tmp);
  633. }
  634. quit:
  635. DEBUG_LEAVE(hr);
  636. return hr;
  637. }
  638. HRESULT
  639. ValidateDispatchArgs(REFIID riid, DISPPARAMS* pdp, VARIANT* pvr, UINT* pae)
  640. {
  641. HRESULT hr = S_OK;
  642. if( !IsEqualIID(riid, IID_NULL) )
  643. {
  644. hr = DISP_E_UNKNOWNINTERFACE;
  645. goto quit;
  646. }
  647. if( !pdp )
  648. {
  649. hr = E_INVALIDARG;
  650. goto quit;
  651. }
  652. if( pae )
  653. {
  654. *pae = 0;
  655. }
  656. if( pvr )
  657. {
  658. VariantInit(pvr);
  659. }
  660. quit:
  661. return hr;
  662. }
  663. HRESULT
  664. ValidateInvokeFlags(WORD flags, WORD accesstype, BOOL bNotMethod)
  665. {
  666. HRESULT hr = S_OK;
  667. if( (flags & ~(DISPATCH_METHOD | DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT)) )
  668. {
  669. hr = E_INVALIDARG;
  670. }
  671. else
  672. {
  673. if( bNotMethod )
  674. {
  675. if( flags & DISPATCH_METHOD )
  676. {
  677. hr = E_NOINTERFACE;
  678. }
  679. else
  680. {
  681. if( (flags & DISPATCH_PROPERTYPUT) && !(accesstype & DISPATCH_PROPERTYPUT) )
  682. {
  683. hr = E_ACCESSDENIED;
  684. }
  685. else
  686. {
  687. if( !(flags & accesstype) )
  688. {
  689. hr = E_FAIL;
  690. }
  691. }
  692. }
  693. }
  694. else
  695. {
  696. if( flags & ~(DISPATCH_METHOD | DISPATCH_PROPERTYGET) )
  697. {
  698. hr = E_NOINTERFACE;
  699. }
  700. }
  701. }
  702. return hr;
  703. }
  704. HRESULT
  705. ValidateArgCount(DISPPARAMS* pdp, DWORD needed, BOOL bHasOptionalArgs, DWORD optional)
  706. {
  707. HRESULT hr = S_OK;
  708. if( bHasOptionalArgs )
  709. {
  710. if( (pdp->cArgs > needed+optional) || (pdp->cArgs < needed) )
  711. {
  712. hr = DISP_E_BADPARAMCOUNT;
  713. }
  714. }
  715. else
  716. {
  717. if( (!needed && pdp->cArgs) || (needed < pdp->cArgs) )
  718. {
  719. hr = DISP_E_BADPARAMCOUNT;
  720. }
  721. else
  722. {
  723. hr = (pdp->cArgs == needed) ? S_OK : DISP_E_PARAMNOTOPTIONAL;
  724. }
  725. }
  726. return hr;
  727. }
  728. HRESULT
  729. HandleDispatchError(LPWSTR id, EXCEPINFO* pei, HRESULT hr)
  730. {
  731. LPWSTR msg = NULL;
  732. switch( hr )
  733. {
  734. case E_POINTER : msg = L"a return pointer parameter was missing"; break;
  735. case E_ACCESSDENIED : msg = L"attempt to modify object failed because it is read-only"; break;
  736. case E_FAIL : msg = L"an unhandled error occurred"; break;
  737. case E_INVALIDARG : msg = L"an argument passed to a property or method was invalid"; break;
  738. case E_NOINTERFACE : msg = L"a property or method was accessed incorrectly"; break;
  739. default : return hr;
  740. }
  741. AddRichErrorInfo(pei, id, msg, hr);
  742. return DISP_E_EXCEPTION;
  743. }
  744. //-----------------------------------------------------------------------------
  745. // string & type manipulation
  746. //-----------------------------------------------------------------------------
  747. char*
  748. __strdup(const char* src)
  749. {
  750. int n = 0;
  751. char* dup = NULL;
  752. if( src )
  753. {
  754. n = strlen(src)+1;
  755. dup = new char[n];
  756. strncpy(dup, src, n);
  757. }
  758. return dup;
  759. }
  760. char*
  761. __strndup(const char* src, int len)
  762. {
  763. char* dup = NULL;
  764. if( src )
  765. {
  766. dup = new char[len+1];
  767. dup[len] = '\0';
  768. strncpy(dup, src, len);
  769. }
  770. return dup;
  771. }
  772. WCHAR*
  773. __wstrdup(const WCHAR* src)
  774. {
  775. int n = 0;
  776. WCHAR* dup = NULL;
  777. if( src )
  778. {
  779. n = wcslen(src)+1;
  780. dup = new WCHAR[n];
  781. wcsncpy(dup, src, n);
  782. }
  783. return dup;
  784. }
  785. WCHAR*
  786. __wstrndup(const WCHAR* src, int len)
  787. {
  788. WCHAR* dup = NULL;
  789. if( src )
  790. {
  791. dup = new WCHAR[len+1];
  792. dup[len] = L'\0';
  793. wcsncpy(dup, src, len);
  794. }
  795. return dup;
  796. }
  797. WCHAR*
  798. __ansitowide(const char* psz)
  799. {
  800. WCHAR* wide = NULL;
  801. int len = 0L;
  802. if( psz )
  803. {
  804. len = strlen(psz);
  805. if( len )
  806. {
  807. ++len;
  808. wide = new WCHAR[len];
  809. MultiByteToWideChar(
  810. CP_ACP,
  811. 0,
  812. psz,
  813. len,
  814. wide,
  815. len
  816. );
  817. }
  818. }
  819. return wide;
  820. }
  821. CHAR*
  822. __widetoansi(const WCHAR* pwsz)
  823. {
  824. CHAR* ansi = NULL;
  825. int len = 0L;
  826. BOOL def = FALSE;
  827. if( pwsz )
  828. {
  829. len = wcslen(pwsz);
  830. if( len )
  831. {
  832. ++len;
  833. ansi = new CHAR[len];
  834. WideCharToMultiByte(
  835. CP_ACP,
  836. 0,
  837. pwsz,
  838. len,
  839. ansi,
  840. len,
  841. "?",
  842. &def
  843. );
  844. }
  845. }
  846. return ansi;
  847. }
  848. BSTR
  849. __ansitobstr(LPCSTR src)
  850. {
  851. BSTR ret = NULL;
  852. LPWSTR wsz = NULL;
  853. if( src )
  854. {
  855. wsz = __ansitowide(src);
  856. ret = SysAllocString(wsz);
  857. SAFEDELETEBUF(wsz);
  858. }
  859. return ret;
  860. }
  861. BSTR
  862. __widetobstr(LPCWSTR wsrc)
  863. {
  864. return (wsrc ? SysAllocString(wsrc) : NULL);
  865. }
  866. BOOL
  867. __isempty(VARIANT var)
  868. {
  869. BOOL isempty = FALSE;
  870. if(
  871. ((V_VT(&var) == VT_EMPTY) || (V_VT(&var) == VT_NULL) || (V_VT(&var) == VT_ERROR)) ||
  872. ((V_VT(&var) == VT_BSTR) && (SysStringLen(V_BSTR(&var)) == 0))
  873. )
  874. {
  875. isempty = TRUE;
  876. }
  877. return isempty;
  878. }
  879. // private
  880. char hex2char(char* hex)
  881. {
  882. register char digit;
  883. digit = (hex[0] >= 'A' ? ((hex[0] & 0xdf) - 'A')+10 : (hex[0] - '0'));
  884. digit *= 16;
  885. digit += (hex[1] >= 'A' ? ((hex[1] & 0xdf) - 'A')+10 : (hex[1] - '0'));
  886. return(digit);
  887. }
  888. char*
  889. __unescape(char* str)
  890. {
  891. register int x;
  892. register int y;
  893. char* str2;
  894. str2 = __strdup(str);
  895. if( str2 )
  896. {
  897. for(x=0, y=0; str2[y]; ++x, ++y)
  898. {
  899. if((str2[x] = str2[y]) == '%')
  900. {
  901. str2[x] = hex2char(&str2[y+1]);
  902. y += 2;
  903. }
  904. }
  905. str2[x] = '\0';
  906. }
  907. return str2;
  908. }