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.

674 lines
11 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. utcls.cpp
  5. Abstract:
  6. Internet Properties base classes
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager (cluster edition)
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. //#include "idlg.h"
  19. #include "mmc.h"
  20. extern "C"
  21. {
  22. #include <lm.h>
  23. }
  24. #define SZ_REG_KEY_BASE _T("Software\\Microsoft\\%s")
  25. BOOL
  26. IsServerLocal(
  27. IN LPCTSTR lpszServer
  28. )
  29. /*++
  30. Routine Description:
  31. Check to see if the given name refers to the local machine
  32. Arguments:
  33. LPCTSTR lpszServer : Server name
  34. Return Value:
  35. TRUE if the given name refers to the local computer, FALSE otherwise
  36. Note:
  37. Doesn't work if the server is an ip address
  38. --*/
  39. {
  40. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  41. DWORD dwSize = sizeof(szComputerName);
  42. //
  43. // CODEWORK(?): we're not checking for all the ip addresses
  44. // on the local box or full dns names.
  45. //
  46. // Try GetComputerNameEx when we're building with NT5
  47. // settings.
  48. //
  49. return (!lstrcmpi(_T("localhost"), PURE_COMPUTER_NAME(lpszServer))
  50. || !lstrcmp( _T("127.0.0.1"), PURE_COMPUTER_NAME(lpszServer)))
  51. || (GetComputerName(szComputerName, &dwSize)
  52. && !lstrcmpi(szComputerName, PURE_COMPUTER_NAME(lpszServer)));
  53. }
  54. BOOL
  55. GetVolumeInformationSystemFlags(
  56. IN LPCTSTR lpszPath,
  57. OUT DWORD * pdwSystemFlags
  58. )
  59. /*++
  60. Routine Description:
  61. Get the system flags for the path in question
  62. Arguments:
  63. LPCTSTR lpszPath : Path
  64. DWORD * pdwSystemFlags : Returns system flags
  65. Return Value:
  66. TRUE for success, FALSE for failure.
  67. --*/
  68. {
  69. ASSERT_WRITE_PTR(pdwSystemFlags);
  70. TRACE("Getting system flags for %s\n", lpszPath);
  71. DWORD dwMaxComponentLength;
  72. TCHAR szRoot[MAX_PATH + 1];
  73. TCHAR szFileSystem[MAX_PATH + 1];
  74. //
  75. // Generating root path
  76. //
  77. if (PathIsUNC(lpszPath))
  78. {
  79. //
  80. // Root path of a UNC path is \\foo\bar\
  81. //
  82. ASSERT(lstrlen(lpszPath) < MAX_PATH);
  83. int cSlashes = 0;
  84. LPCTSTR lpszSrc = lpszPath;
  85. LPTSTR lpszDst = szRoot;
  86. while (cSlashes < 4 && *lpszSrc)
  87. {
  88. if ((*lpszDst++ = *lpszSrc++) == '\\')
  89. {
  90. ++cSlashes;
  91. }
  92. }
  93. if (!*lpszSrc)
  94. {
  95. *lpszDst++ = '\\';
  96. }
  97. *lpszDst = '\0';
  98. }
  99. else
  100. {
  101. ::wsprintf(szRoot, _T("%c:\\"), *lpszPath);
  102. }
  103. TRACE("Root path is %s\n", szRoot);
  104. return ::GetVolumeInformation(
  105. szRoot,
  106. NULL,
  107. 0,
  108. NULL,
  109. &dwMaxComponentLength,
  110. pdwSystemFlags,
  111. szFileSystem,
  112. sizeof(szFileSystem) / sizeof(TCHAR)
  113. );
  114. }
  115. LPCTSTR
  116. GenerateRegistryKey(
  117. OUT CString & strBuffer,
  118. IN LPCTSTR lpszSubKey OPTIONAL
  119. )
  120. /*++
  121. Routine Description:
  122. Generate a registry key name based on the current app, and a
  123. provided subkey (optional)
  124. Arguments:
  125. CString & strBuffer : Buffer to create registry key name into.
  126. LPCTSTR lpszSubKey : Subkey name or NULL
  127. Return Value:
  128. Pointer to the registry key value
  129. --*/
  130. {
  131. try
  132. {
  133. //
  134. // Use the app name as the primary registry name
  135. //
  136. CString app_name;
  137. app_name.LoadString(_Module.GetResourceInstance(), IDS_APP_TITLE);
  138. strBuffer.Format(SZ_REG_KEY_BASE, app_name);
  139. if (lpszSubKey)
  140. {
  141. strBuffer += _T("\\");
  142. strBuffer += lpszSubKey;
  143. }
  144. TRACE("Registry key is %s\n", strBuffer);
  145. }
  146. catch(std::bad_alloc)
  147. {
  148. TRACEEOLID("!!!exception building regkey");
  149. return NULL;
  150. }
  151. return strBuffer;
  152. }
  153. static int
  154. CountCharsToDoubleNull(
  155. IN LPCTSTR lp
  156. )
  157. /*++
  158. Routine Description:
  159. Count TCHARS up to and including the double NULL.
  160. Arguments:
  161. LPCTSTR lp : TCHAR Stream
  162. Return Value:
  163. Number of chars up to and including the double NULL
  164. --*/
  165. {
  166. int cChars = 0;
  167. for(;;)
  168. {
  169. ++cChars;
  170. if (lp[0] == _T('\0') && lp[1] == _T('\0'))
  171. {
  172. return ++cChars;
  173. }
  174. ++lp;
  175. }
  176. }
  177. CStringListEx::CStringListEx() : std::list<CString> ()
  178. {
  179. }
  180. CStringListEx::~CStringListEx()
  181. {
  182. }
  183. void
  184. CStringListEx::PushBack(LPCTSTR str)
  185. {
  186. push_back(str);
  187. }
  188. void
  189. CStringListEx::Clear()
  190. {
  191. clear();
  192. }
  193. DWORD
  194. CStringListEx::ConvertFromDoubleNullList(LPCTSTR lpstrSrc, int cChars)
  195. /*++
  196. Routine Description:
  197. Convert a double null terminate list of null terminated strings to a more
  198. manageable CStringList
  199. Arguments:
  200. LPCTSTR lpstrSrc : Source list of strings
  201. int cChars : Number of characters in double NULL list. if
  202. -1, autodetermine length
  203. Return Value:
  204. ERROR_SUCCESS if the list was converted properly
  205. ERROR_INVALID_PARAMETER if the list was empty
  206. ERROR_NOT_ENOUGH_MEMORY if there was a mem exception
  207. --*/
  208. {
  209. DWORD err = ERROR_SUCCESS;
  210. if (lpstrSrc == NULL)
  211. {
  212. return ERROR_INVALID_PARAMETER;
  213. }
  214. if (cChars < 0)
  215. {
  216. //
  217. // Calculate our own size. This might be off if multiple
  218. // blank linkes (0) appear in the multi_sz, so the character
  219. // size is definitely preferable
  220. //
  221. cChars = CountCharsToDoubleNull(lpstrSrc);
  222. }
  223. try
  224. {
  225. clear();
  226. if (cChars == 2 && *lpstrSrc == _T('\0'))
  227. {
  228. //
  229. // Special case: MULTI_SZ containing only
  230. // a double NULL are in fact blank entirely.
  231. //
  232. // N.B. IMHO this is a metabase bug -- RonaldM
  233. //
  234. --cChars;
  235. }
  236. //
  237. // Grab strings until only the final NULL remains
  238. //
  239. while (cChars > 1)
  240. {
  241. CString strTmp = lpstrSrc;
  242. push_back(strTmp);
  243. lpstrSrc += (strTmp.GetLength() + 1);
  244. cChars -= (strTmp.GetLength() + 1);
  245. }
  246. }
  247. catch(std::bad_alloc)
  248. {
  249. TRACEEOLID("!!! exception building stringlist");
  250. err = ERROR_NOT_ENOUGH_MEMORY;
  251. }
  252. return err;
  253. }
  254. DWORD
  255. CStringListEx::ConvertToDoubleNullList(
  256. OUT DWORD & cchDest,
  257. OUT LPTSTR & lpstrDest
  258. )
  259. /*++
  260. Routine Description:
  261. Flatten the string list into a double null terminated list
  262. of null terminated strings.
  263. Arguments:
  264. CStringList & strlSrc : Source string list
  265. DWORD & cchDest : Size in characters of the resultant array
  266. (including terminating NULLs)
  267. LPTSTR & lpstrDest : Allocated flat array.
  268. Return Value:
  269. ERROR_SUCCESS if the list was converted properly
  270. ERROR_INVALID_PARAMETER if the list was empty
  271. ERROR_NOT_ENOUGH_MEMORY if there was a mem exception
  272. --*/
  273. {
  274. cchDest = 0;
  275. lpstrDest = NULL;
  276. BOOL fNullPad = FALSE;
  277. //
  278. // Compute total size in characters
  279. //
  280. CStringListEx::iterator it = begin();
  281. while (it != end())
  282. {
  283. CString & str = (*it++);
  284. // TRACEEOLID(str);
  285. cchDest += str.GetLength() + 1;
  286. }
  287. if (!cchDest)
  288. {
  289. //
  290. // Special case: A totally empty MULTI_SZ
  291. // in fact consists of 2 (final) NULLS, instead
  292. // of 1 (final) NULL. This is required by the
  293. // metabase, but should be a bug. See note
  294. // at reversal function above.
  295. //
  296. ++cchDest;
  297. fNullPad = TRUE;
  298. }
  299. //
  300. // Remember final NULL
  301. //
  302. cchDest += 1;
  303. lpstrDest = new TCHAR[cchDest];
  304. if (lpstrDest == NULL)
  305. {
  306. return ERROR_NOT_ENOUGH_MEMORY;
  307. }
  308. LPTSTR pch = lpstrDest;
  309. it = begin();
  310. while (it != end())
  311. {
  312. CString & str = (*it++);
  313. lstrcpy(pch, (LPCTSTR)str);
  314. pch += str.GetLength();
  315. *pch++ = _T('\0');
  316. }
  317. *pch++ = _T('\0');
  318. if (fNullPad)
  319. {
  320. *pch++ = _T('\0');
  321. }
  322. return ERROR_SUCCESS;
  323. }
  324. //
  325. // CBlob Implementation
  326. //
  327. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  328. CBlob::CBlob()
  329. /*++
  330. Routine Description:
  331. NULL constructor
  332. Arguments:
  333. None
  334. Return Value:
  335. N/A
  336. --*/
  337. : m_pbItem(NULL),
  338. m_dwSize(0L)
  339. {
  340. }
  341. CBlob::CBlob(
  342. IN DWORD dwSize,
  343. IN PBYTE pbItem,
  344. IN BOOL fMakeCopy
  345. )
  346. /*++
  347. Routine Description:
  348. Constructor
  349. Arguments:
  350. DWORD dwSize : Size of memory block
  351. PBYTE pbItem : Pointer to memory block
  352. BOOL fMakeCopy : If TRUE, makes a copy of the memory block.
  353. If FALSE, takes ownership of the pointer.
  354. Return Value:
  355. N/A
  356. --*/
  357. : m_pbItem(NULL),
  358. m_dwSize(0L)
  359. {
  360. SetValue(dwSize, pbItem, fMakeCopy);
  361. }
  362. CBlob::CBlob(
  363. IN const CBlob & blob
  364. )
  365. /*++
  366. Routine Description:
  367. Copy constructor
  368. Arguments:
  369. const CBlob & blob : Source blob
  370. Return Value:
  371. N/A
  372. Notes:
  373. This contructor makes a copy of the memory block in question.
  374. --*/
  375. : m_pbItem(NULL),
  376. m_dwSize(0L)
  377. {
  378. SetValue(blob.GetSize(), blob.m_pbItem, TRUE);
  379. }
  380. void
  381. CBlob::SetValue(
  382. IN DWORD dwSize,
  383. IN PBYTE pbItem,
  384. IN BOOL fMakeCopy OPTIONAL
  385. )
  386. /*++
  387. Routine Description:
  388. Assign the value to this binary object. If fMakeCopy is FALSE,
  389. the blob will take ownership of the pointer, otherwise a copy
  390. will be made.
  391. Arguments:
  392. DWORD dwSize : Size in bytes
  393. PBYTE pbItem : Byte streadm
  394. BOOL fMakeCopy : If true, make a copy, else assign pointer
  395. Return Value:
  396. None
  397. --*/
  398. {
  399. ASSERT_READ_PTR2(pbItem, dwSize);
  400. if (!IsEmpty())
  401. {
  402. TRACEEOLID("Assigning value to non-empty blob. Cleaning up");
  403. CleanUp();
  404. }
  405. if (dwSize > 0L)
  406. {
  407. //
  408. // Make private copy
  409. //
  410. m_dwSize = dwSize;
  411. if (fMakeCopy)
  412. {
  413. m_pbItem = new BYTE[m_dwSize];
  414. if (NULL != m_pbItem)
  415. CopyMemory(m_pbItem, pbItem, dwSize);
  416. }
  417. else
  418. {
  419. m_pbItem = pbItem;
  420. }
  421. }
  422. }
  423. void
  424. CBlob::CleanUp()
  425. /*++
  426. Routine Description:
  427. Delete data pointer, and reset pointer and size.
  428. Arguments:
  429. None
  430. Return Value:
  431. None
  432. --*/
  433. {
  434. if (m_pbItem)
  435. {
  436. delete [] m_pbItem;
  437. }
  438. m_pbItem = NULL;
  439. m_dwSize = 0L;
  440. }
  441. CBlob &
  442. CBlob::operator =(
  443. IN const CBlob & blob
  444. )
  445. /*++
  446. Routine Description:
  447. Assign values from another CBlob.
  448. Arguments:
  449. const CBlob & blob : Source blob
  450. Return Value:
  451. Reference to this object
  452. --*/
  453. {
  454. //
  455. // Make copy of data
  456. //
  457. SetValue(blob.GetSize(), blob.m_pbItem, TRUE);
  458. return *this;
  459. }
  460. BOOL
  461. CBlob::operator ==(
  462. IN const CBlob & blob
  463. ) const
  464. /*++
  465. Routine Description:
  466. Compare two binary large objects. In order to match, the objects
  467. must be the same size, and byte identical.
  468. Arguments:
  469. const CBlob & blob : Blob to compare against.
  470. Return Value:
  471. TRUE if the objects match, FALSE otherwise.
  472. --*/
  473. {
  474. if (GetSize() != blob.GetSize())
  475. {
  476. return FALSE;
  477. }
  478. return memcmp(m_pbItem, blob.m_pbItem, GetSize()) == 0;
  479. }