Source code of Windows XP (NT5)
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.

458 lines
10 KiB

  1. // Util.cpp : Implementation of ds routines and classes
  2. //+-------------------------------------------------------------------------
  3. //
  4. // Microsoft Windows
  5. // Copyright (C) Microsoft Corporation, 1992 - 1999
  6. //
  7. // File: Util.cpp
  8. //
  9. // Contents: Utility functions
  10. //
  11. // History: 02-Oct-96 WayneSc Created
  12. //
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "stdafx.h"
  16. #include "util.h"
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. #define MAX_STRING 1024
  23. //+----------------------------------------------------------------------------
  24. //
  25. // Function: LoadStringToTchar
  26. //
  27. // Sysnopsis: Loads the given string into an allocated buffer that must be
  28. // caller freed using delete.
  29. //
  30. //-----------------------------------------------------------------------------
  31. BOOL LoadStringToTchar(int ids, PTSTR * pptstr)
  32. {
  33. TCHAR szBuf[MAX_STRING];
  34. if (!LoadString(_Module.GetModuleInstance(), ids, szBuf, MAX_STRING - 1))
  35. {
  36. return FALSE;
  37. }
  38. *pptstr = new TCHAR[_tcslen(szBuf) + 1];
  39. if (*pptstr == NULL)
  40. {
  41. return FALSE;
  42. };
  43. _tcscpy(*pptstr, szBuf);
  44. return TRUE;
  45. }
  46. //
  47. // These routines courtesy of Felix Wong -- JonN 2/24/98
  48. //
  49. // just guessing at what Felix meant by these -- JonN 2/24/98
  50. #define RRETURN(hr) { ASSERT( SUCCEEDED(hr) ); return hr; }
  51. #define BAIL_ON_FAILURE if ( FAILED(hr) ) { ASSERT(FALSE); goto error; }
  52. //////////////////////////////////////////////////////////////////////////
  53. // Variant Utilitites
  54. //
  55. HRESULT BinaryToVariant(DWORD Length,
  56. BYTE* pByte,
  57. VARIANT* lpVarDestObject)
  58. {
  59. HRESULT hr = S_OK;
  60. SAFEARRAY *aList = NULL;
  61. SAFEARRAYBOUND aBound;
  62. CHAR HUGEP *pArray = NULL;
  63. aBound.lLbound = 0;
  64. aBound.cElements = Length;
  65. aList = SafeArrayCreate( VT_UI1, 1, &aBound );
  66. if ( aList == NULL )
  67. {
  68. hr = E_OUTOFMEMORY;
  69. BAIL_ON_FAILURE(hr);
  70. }
  71. hr = SafeArrayAccessData( aList, (void HUGEP * FAR *) &pArray );
  72. BAIL_ON_FAILURE(hr);
  73. memcpy( pArray, pByte, aBound.cElements );
  74. SafeArrayUnaccessData( aList );
  75. V_VT(lpVarDestObject) = VT_ARRAY | VT_UI1;
  76. V_ARRAY(lpVarDestObject) = aList;
  77. RRETURN(hr);
  78. error:
  79. if ( aList )
  80. {
  81. SafeArrayDestroy( aList );
  82. }
  83. RRETURN(hr);
  84. }
  85. HRESULT HrVariantToStringList(const CComVariant& refvar,
  86. CStringList& refstringlist)
  87. {
  88. HRESULT hr = S_OK;
  89. long start, end, current;
  90. if (V_VT(&refvar) == VT_BSTR)
  91. {
  92. refstringlist.AddHead( V_BSTR(&refvar) );
  93. return S_OK;
  94. }
  95. //
  96. // Check the VARIANT to make sure we have
  97. // an array of variants.
  98. //
  99. if ( V_VT(&refvar) != ( VT_ARRAY | VT_VARIANT ) )
  100. {
  101. ASSERT(FALSE);
  102. return E_UNEXPECTED;
  103. }
  104. SAFEARRAY *saAttributes = V_ARRAY( &refvar );
  105. //
  106. // Figure out the dimensions of the array.
  107. //
  108. hr = SafeArrayGetLBound( saAttributes, 1, &start );
  109. if( FAILED(hr) )
  110. return hr;
  111. hr = SafeArrayGetUBound( saAttributes, 1, &end );
  112. if( FAILED(hr) )
  113. return hr;
  114. CComVariant SingleResult;
  115. //
  116. // Process the array elements.
  117. //
  118. for ( current = start; current <= end; current++)
  119. {
  120. hr = SafeArrayGetElement( saAttributes, &current, &SingleResult );
  121. if( FAILED(hr) )
  122. return hr;
  123. if ( V_VT(&SingleResult) != VT_BSTR )
  124. return E_UNEXPECTED;
  125. refstringlist.AddHead( V_BSTR(&SingleResult) );
  126. }
  127. return S_OK;
  128. } // VariantToStringList()
  129. HRESULT HrStringListToVariant(CComVariant& refvar,
  130. const CStringList& refstringlist)
  131. {
  132. HRESULT hr = S_OK;
  133. int cCount = (int)refstringlist.GetCount();
  134. SAFEARRAYBOUND rgsabound[1];
  135. rgsabound[0].lLbound = 0;
  136. rgsabound[0].cElements = cCount;
  137. SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
  138. if (NULL == psa)
  139. return E_OUTOFMEMORY;
  140. V_VT(&refvar) = VT_VARIANT|VT_ARRAY;
  141. V_ARRAY(&refvar) = psa;
  142. POSITION pos = refstringlist.GetHeadPosition();
  143. long i;
  144. for (i = 0; i < cCount, pos != NULL; i++)
  145. {
  146. CComVariant SingleResult; // declare inside loop. Otherwise, throws
  147. // exception in destructor if nothing added.
  148. V_VT(&SingleResult) = VT_BSTR;
  149. V_BSTR(&SingleResult) = T2BSTR((LPCTSTR)refstringlist.GetNext(pos));
  150. hr = SafeArrayPutElement(psa, &i, &SingleResult);
  151. if( FAILED(hr) )
  152. return hr;
  153. }
  154. if (i != cCount || pos != NULL)
  155. return E_UNEXPECTED;
  156. return hr;
  157. } // StringListToVariant()
  158. //////////////////////////////////////////////////////////
  159. // streaming helper functions
  160. HRESULT SaveStringHelper(LPCWSTR pwsz, IStream* pStm)
  161. {
  162. ASSERT(pStm);
  163. ULONG nBytesWritten;
  164. HRESULT hr;
  165. //
  166. // wcslen returns a size_t and to make that consoles work the same
  167. // on any platform we always convert to a DWORD
  168. //
  169. DWORD nLen = static_cast<DWORD>(wcslen(pwsz)+1); // WCHAR including NULL
  170. hr = pStm->Write((void*)&nLen, sizeof(DWORD),&nBytesWritten);
  171. ASSERT(nBytesWritten == sizeof(DWORD));
  172. if (FAILED(hr))
  173. return hr;
  174. hr = pStm->Write((void*)pwsz, sizeof(WCHAR)*nLen,&nBytesWritten);
  175. ASSERT(nBytesWritten == sizeof(WCHAR)*nLen);
  176. TRACE(_T("SaveStringHelper(<%s> nLen = %d\n"),pwsz,nLen);
  177. return hr;
  178. }
  179. HRESULT LoadStringHelper(CString& sz, IStream* pStm)
  180. {
  181. ASSERT(pStm);
  182. HRESULT hr;
  183. ULONG nBytesRead;
  184. DWORD nLen = 0;
  185. hr = pStm->Read((void*)&nLen,sizeof(DWORD), &nBytesRead);
  186. ASSERT(nBytesRead == sizeof(DWORD));
  187. if (FAILED(hr) || (nBytesRead != sizeof(DWORD)))
  188. return hr;
  189. hr = pStm->Read((void*)sz.GetBuffer(nLen),sizeof(WCHAR)*nLen, &nBytesRead);
  190. ASSERT(nBytesRead == sizeof(WCHAR)*nLen);
  191. sz.ReleaseBuffer();
  192. TRACE(_T("LoadStringHelper(<%s> nLen = %d\n"),(LPCTSTR)sz,nLen);
  193. return hr;
  194. }
  195. HRESULT SaveDWordHelper(IStream* pStm, DWORD dw)
  196. {
  197. ULONG nBytesWritten;
  198. HRESULT hr = pStm->Write((void*)&dw, sizeof(DWORD),&nBytesWritten);
  199. if (nBytesWritten < sizeof(DWORD))
  200. hr = STG_E_CANTSAVE;
  201. return hr;
  202. }
  203. HRESULT LoadDWordHelper(IStream* pStm, DWORD* pdw)
  204. {
  205. ULONG nBytesRead;
  206. HRESULT hr = pStm->Read((void*)pdw,sizeof(DWORD), &nBytesRead);
  207. ASSERT(nBytesRead == sizeof(DWORD));
  208. return hr;
  209. }
  210. void GetCurrentTimeStampMinusInterval(DWORD dwDays,
  211. LARGE_INTEGER* pLI)
  212. {
  213. ASSERT(pLI);
  214. FILETIME ftCurrent;
  215. GetSystemTimeAsFileTime(&ftCurrent);
  216. pLI->LowPart = ftCurrent.dwLowDateTime;
  217. pLI->HighPart = ftCurrent.dwHighDateTime;
  218. pLI->QuadPart -= ((((ULONGLONG)dwDays * 24) * 60) * 60) * 10000000;
  219. }
  220. /////////////////////////////////////////////////////////////////////
  221. // CCommandLineOptions
  222. //
  223. // helper function to parse a single command and match it with a given switch
  224. //
  225. BOOL _LoadCommandLineValue(IN LPCWSTR lpszSwitch,
  226. IN LPCWSTR lpszArg,
  227. OUT CString* pszValue)
  228. {
  229. ASSERT(lpszSwitch != NULL);
  230. ASSERT(lpszArg != NULL);
  231. int nSwitchLen = lstrlen(lpszSwitch); // not counting NULL
  232. // check if the arg is the one we look for
  233. if (_wcsnicmp(lpszSwitch, lpszArg, nSwitchLen) == 0)
  234. {
  235. // got it, copy the value
  236. if (pszValue != NULL)
  237. (*pszValue) = lpszArg+nSwitchLen;
  238. return TRUE;
  239. }
  240. // not found, empty string
  241. if (pszValue != NULL)
  242. pszValue->Empty();
  243. return FALSE;
  244. }
  245. void CCommandLineOptions::Initialize()
  246. {
  247. // command line overrides the snapin understands,
  248. // not subject to localization
  249. static LPCWSTR lpszOverrideDomainCommandLine = L"/Domain=";
  250. static LPCWSTR lpszOverrideServerCommandLine = L"/Server=";
  251. static LPCWSTR lpszOverrideRDNCommandLine = L"/RDN=";
  252. static LPCWSTR lpszOverrideSavedQueriesCommandLine = L"/Queries=";
  253. #ifdef DBG
  254. static LPCWSTR lpszOverrideNoNameCommandLine = L"/NoName";
  255. #endif
  256. // do it only once
  257. if (m_bInit)
  258. {
  259. return;
  260. }
  261. m_bInit = TRUE;
  262. //
  263. // see if we have command line arguments
  264. //
  265. LPCWSTR * lpServiceArgVectors; // Array of pointers to string
  266. int cArgs = 0; // Count of arguments
  267. lpServiceArgVectors = (LPCWSTR *)CommandLineToArgvW(GetCommandLineW(), OUT &cArgs);
  268. if (lpServiceArgVectors == NULL)
  269. {
  270. // none, just return
  271. return;
  272. }
  273. // loop and search for pertinent strings
  274. for (int i = 1; i < cArgs; i++)
  275. {
  276. ASSERT(lpServiceArgVectors[i] != NULL);
  277. TRACE (_T("command line arg: %s\n"), lpServiceArgVectors[i]);
  278. if (_LoadCommandLineValue(lpszOverrideDomainCommandLine,
  279. lpServiceArgVectors[i], &m_szOverrideDomainName))
  280. {
  281. continue;
  282. }
  283. if (_LoadCommandLineValue(lpszOverrideServerCommandLine,
  284. lpServiceArgVectors[i], &m_szOverrideServerName))
  285. {
  286. continue;
  287. }
  288. if (_LoadCommandLineValue(lpszOverrideRDNCommandLine,
  289. lpServiceArgVectors[i], &m_szOverrideRDN))
  290. {
  291. continue;
  292. }
  293. if (_LoadCommandLineValue(lpszOverrideSavedQueriesCommandLine,
  294. lpServiceArgVectors[i], &m_szSavedQueriesXMLFile))
  295. {
  296. continue;
  297. }
  298. #ifdef DBG
  299. if (_LoadCommandLineValue(lpszOverrideNoNameCommandLine,
  300. lpServiceArgVectors[i], NULL))
  301. {
  302. continue;
  303. }
  304. #endif
  305. }
  306. LocalFree(lpServiceArgVectors);
  307. }
  308. ////////////////////////////////////////////////////////////////
  309. // Type conversions for LARGE_INTEGERs
  310. void wtoli(LPCWSTR p, LARGE_INTEGER& liOut)
  311. {
  312. liOut.QuadPart = 0;
  313. BOOL bNeg = FALSE;
  314. if (*p == L'-')
  315. {
  316. bNeg = TRUE;
  317. p++;
  318. }
  319. while (*p != L'\0')
  320. {
  321. liOut.QuadPart = 10 * liOut.QuadPart + (*p-L'0');
  322. p++;
  323. }
  324. if (bNeg)
  325. {
  326. liOut.QuadPart *= -1;
  327. }
  328. }
  329. void litow(LARGE_INTEGER& li, CString& sResult)
  330. {
  331. LARGE_INTEGER n;
  332. n.QuadPart = li.QuadPart;
  333. if (n.QuadPart == 0)
  334. {
  335. sResult = L"0";
  336. }
  337. else
  338. {
  339. CString sNeg;
  340. sResult = L"";
  341. if (n.QuadPart < 0)
  342. {
  343. sNeg = CString(L'-');
  344. n.QuadPart *= -1;
  345. }
  346. while (n.QuadPart > 0)
  347. {
  348. sResult += CString(L'0' + static_cast<WCHAR>(n.QuadPart % 10));
  349. n.QuadPart = n.QuadPart / 10;
  350. }
  351. sResult = sResult + sNeg;
  352. }
  353. sResult.MakeReverse();
  354. }
  355. // This wrapper function required to make prefast shut up when we are
  356. // initializing a critical section in a constructor.
  357. void
  358. ExceptionPropagatingInitializeCriticalSection(LPCRITICAL_SECTION critsec)
  359. {
  360. __try
  361. {
  362. ::InitializeCriticalSection(critsec);
  363. }
  364. //
  365. // propagate the exception to our caller.
  366. //
  367. __except (EXCEPTION_CONTINUE_SEARCH)
  368. {
  369. }
  370. }