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.

530 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: listvw.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. #include <commctrl.h>
  13. #include <assert.h>
  14. #include "celib.h"
  15. #include "listvw.h"
  16. extern HINSTANCE g_hInstance;
  17. typedef struct _DISPLAYSTRING_EXPANSION
  18. {
  19. LPCWSTR szContractedToken;
  20. LPCWSTR szExpansionString;
  21. } DISPLAYSTRING_EXPANSION, *PDISPLAYSTRING_EXPANSION;
  22. DISPLAYSTRING_EXPANSION displayStrings[] =
  23. {
  24. { wszFCSAPARM_SERVERDNSNAME, L"%SERVER_DNS_NAME%"},
  25. { wszFCSAPARM_SERVERSHORTNAME, L"%SERVER_SHORT_NAME%"},
  26. { wszFCSAPARM_SANITIZEDCANAME, L"%CA_NAME%"},
  27. { wszFCSAPARM_CERTFILENAMESUFFIX, L"%CERT_SUFFIX%"},
  28. { wszFCSAPARM_DOMAINDN, L"%DOMAIN_NAME%"},
  29. { wszFCSAPARM_CONFIGDN, L"%CONFIG_NAME%"},
  30. { wszFCSAPARM_SANITIZEDCANAMEHASH, L"%CA_NAME_HASH%"},
  31. { wszFCSAPARM_CRLFILENAMESUFFIX, L"%CRL_SUFFIX%"},
  32. };
  33. DISPLAYSTRING_EXPANSION escapedStrings[] =
  34. {
  35. { L"%9", L"%%"},
  36. };
  37. HRESULT ValidateTokens(
  38. IN OUT LPWSTR szURL,
  39. OUT DWORD* pchBadBegin,
  40. OUT DWORD* pchBadEnd)
  41. {
  42. HRESULT hr = S_FALSE;
  43. int i;
  44. LPWSTR pszMatch;
  45. LPWSTR pszFound = szURL;
  46. WCHAR rgszToken[MAX_PATH];
  47. *pchBadBegin = -1;
  48. *pchBadEnd = -1;
  49. // look for escape token open marker
  50. while(NULL != (pszFound = wcschr(pszFound, L'%')))
  51. {
  52. pszMatch = wcschr(&pszFound[1], L'%'); // look for closing marker
  53. if (pszMatch == NULL)
  54. goto Ret;
  55. DWORD dwChars = SAFE_SUBTRACT_POINTERS(pszMatch, pszFound) +1; // dwChars is chars including markers
  56. if (dwChars == 2)
  57. goto NextMatch; // %% is valid escape sequence
  58. if (dwChars > MAX_PATH)
  59. goto Ret; // invalid escape token!
  60. // isolate the token
  61. CopyMemory(rgszToken, pszFound, dwChars * sizeof(WCHAR));
  62. rgszToken[dwChars] = L'\0';
  63. for (i=0; i<ARRAYSIZE(displayStrings); i++)
  64. {
  65. if (0 == _wcsicmp(rgszToken, displayStrings[i].szExpansionString))
  66. {
  67. // copy from displayStrings -- these are guaranteed to be properly uppercased
  68. CopyMemory(pszFound, displayStrings[i].szExpansionString, dwChars * sizeof(WCHAR));
  69. goto NextMatch;
  70. }
  71. }
  72. // if we get here, we found no match
  73. goto Ret;
  74. NextMatch:
  75. pszFound = ++pszMatch;
  76. }
  77. hr = S_OK;
  78. Ret:
  79. if (hr != S_OK)
  80. {
  81. *pchBadBegin = SAFE_SUBTRACT_POINTERS(pszFound, szURL); // offset to first incorrect %
  82. if (pszMatch)
  83. *pchBadEnd = SAFE_SUBTRACT_POINTERS(pszMatch, szURL) + 1; // offset past final incorrect %
  84. }
  85. return hr;
  86. }
  87. HRESULT
  88. ExpandDisplayString(
  89. IN LPCWSTR szContractedString,
  90. OUT LPWSTR* ppszDisplayString)
  91. {
  92. HRESULT hr;
  93. DWORD dwChars;
  94. int i, iescapedStrings;
  95. LPWSTR pszTempContracted = NULL;
  96. LPWSTR pszFound;
  97. // account for %% escaping in contracted string --
  98. // replace "%%" with %9, let FormatString expand to "%%"
  99. pszTempContracted = (LPWSTR)LocalAlloc(LMEM_FIXED, (wcslen(szContractedString)+1)*sizeof(WCHAR));
  100. if (pszTempContracted == NULL)
  101. {
  102. hr = E_OUTOFMEMORY;
  103. goto Ret;
  104. }
  105. wcscpy(pszTempContracted, szContractedString);
  106. pszFound = wcsstr(pszTempContracted, L"%%");
  107. while(pszFound)
  108. {
  109. CopyMemory(pszFound, escapedStrings[0].szContractedToken, wcslen(escapedStrings[0].szContractedToken)*sizeof(WCHAR));
  110. pszFound = wcsstr(pszFound, L"%%");
  111. }
  112. LPCWSTR args[ARRAYSIZE(displayStrings)+ARRAYSIZE(escapedStrings)];
  113. for (i=0; i<ARRAYSIZE(displayStrings); i++)
  114. {
  115. args[i] = displayStrings[i].szExpansionString;
  116. }
  117. // and tell FormatString to expand %9 to %%
  118. for (iescapedStrings=0; iescapedStrings<ARRAYSIZE(escapedStrings); iescapedStrings++)
  119. {
  120. args[i+iescapedStrings] = escapedStrings[iescapedStrings].szExpansionString;
  121. }
  122. dwChars = FormatMessage(
  123. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING,
  124. pszTempContracted,
  125. 0, //msgid
  126. 0, //langid
  127. (LPWSTR)ppszDisplayString,
  128. 1, // minimum chars to alloc
  129. (va_list *)args);
  130. if (dwChars == 0)
  131. {
  132. hr = GetLastError();
  133. hr = HRESULT_FROM_WIN32(hr);
  134. goto Ret;
  135. }
  136. hr = S_OK;
  137. Ret:
  138. if (pszTempContracted)
  139. LocalFree(pszTempContracted);
  140. return hr;
  141. }
  142. HRESULT
  143. ContractDisplayString(
  144. IN LPCWSTR szDisplayString,
  145. OUT LPWSTR* ppContractedString)
  146. {
  147. HRESULT hr;
  148. int i;
  149. *ppContractedString = (LPWSTR)LocalAlloc(LMEM_FIXED, (wcslen(szDisplayString)+1) * sizeof(WCHAR));
  150. if (*ppContractedString == NULL)
  151. {
  152. hr = E_OUTOFMEMORY;
  153. goto Ret;
  154. }
  155. wcscpy(*ppContractedString, szDisplayString);
  156. for (i=0; i<ARRAYSIZE(displayStrings); i++)
  157. {
  158. DWORD chContractedToken, chExpansionString;
  159. LPWSTR pszFound = wcsstr(*ppContractedString, displayStrings[i].szExpansionString);
  160. while(pszFound)
  161. {
  162. // calc commonly used values
  163. chContractedToken = wcslen(displayStrings[i].szContractedToken);
  164. chExpansionString = wcslen(displayStrings[i].szExpansionString);
  165. // replace with token
  166. CopyMemory(pszFound, displayStrings[i].szContractedToken, chContractedToken*sizeof(WCHAR));
  167. // slide rest of string left
  168. MoveMemory(
  169. &pszFound[chContractedToken], // destination
  170. &pszFound[chExpansionString], // source
  171. (wcslen(&pszFound[chExpansionString])+1) *sizeof(WCHAR) );
  172. // step Found over insertion
  173. pszFound += chContractedToken;
  174. // find any other ocurrences after this one
  175. pszFound = wcsstr(pszFound, displayStrings[i].szExpansionString);
  176. }
  177. }
  178. hr = S_OK;
  179. Ret:
  180. return hr;
  181. }
  182. void AddStringToCheckList(
  183. HWND hWndListView,
  184. LPCWSTR szText,
  185. LPVOID pvData,
  186. BOOL fCheck)
  187. {
  188. LVITEMW lvI;
  189. ZeroMemory(&lvI, sizeof(lvI));
  190. //
  191. // set up the fields in the list view item struct that don't change from item to item
  192. //
  193. lvI.mask = LVIF_TEXT | LVIF_PARAM;
  194. lvI.pszText = (LPWSTR)szText;
  195. lvI.iSubItem = 0;
  196. lvI.lParam = (LPARAM)pvData;
  197. lvI.iItem = ListView_GetItemCount(hWndListView);
  198. lvI.cchTextMax = wcslen(szText);
  199. ListView_InsertItem(hWndListView, &lvI);
  200. ListView_SetCheckState(hWndListView, lvI.iItem, fCheck);
  201. ListView_SetColumnWidth(hWndListView, 0, LVSCW_AUTOSIZE);
  202. }
  203. DWORD DetermineURLType(PCERTSVR_URL_PARSING prgURLParsing, int cURLParsingEntries, LPCWSTR szCandidateURL)
  204. {
  205. int iURLTypeMatch;
  206. // determine URL type
  207. WCHAR rgsz[6]; // "http:\0" , etc
  208. lstrcpyn(rgsz, szCandidateURL, 6);
  209. WCHAR* pch = wcschr(rgsz, L':'); // find ':'
  210. if (NULL == pch)
  211. return -1; // invalid item
  212. pch[1] = '\0'; // whack the elt after :
  213. // find the prefix in our list of known protocols
  214. for (iURLTypeMatch=0; iURLTypeMatch<cURLParsingEntries; iURLTypeMatch++)
  215. {
  216. if (0 == _wcsicmp(rgsz, prgURLParsing[iURLTypeMatch].szKnownPrefix))
  217. break;
  218. }
  219. if (iURLTypeMatch == cURLParsingEntries) // no match
  220. return -1;
  221. return iURLTypeMatch;
  222. }
  223. HRESULT WriteChanges(HWND hListView, HKEY hkeyStorage, PCERTSVR_URL_PARSING prgURLParsing, DWORD cURLParsingEntries)
  224. {
  225. HRESULT hr = S_OK;
  226. // empty item to dump to
  227. LV_ITEM lvI;
  228. ZeroMemory(&lvI, sizeof(lvI));
  229. lvI.mask = LVIF_TEXT;
  230. WCHAR szText[MAX_PATH+1];
  231. lvI.pszText = szText;
  232. lvI.cchTextMax = MAX_PATH;
  233. LPWSTR pszContracted = NULL;
  234. int iURLArrayLen = cURLParsingEntries;
  235. int iURLTypeMatch;
  236. DWORD* rgchszzEntries = NULL;
  237. LPWSTR* rgszzEntries = NULL;
  238. // entries will be sorted into one of the following
  239. rgchszzEntries = (DWORD*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(DWORD) * cURLParsingEntries);
  240. if (NULL == rgchszzEntries)
  241. {
  242. hr = E_OUTOFMEMORY;
  243. goto Ret;
  244. }
  245. rgszzEntries = (LPWSTR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(LPWSTR) * cURLParsingEntries);
  246. if (NULL == rgszzEntries)
  247. {
  248. hr = E_OUTOFMEMORY;
  249. goto Ret;
  250. }
  251. // enumerate through all the items and add to the arrays
  252. for (lvI.iItem=0; ; lvI.iItem++)
  253. {
  254. BOOL fCheck = TRUE;
  255. LPWSTR pszTmp;
  256. // go until we hit end-of-list
  257. if (!ListView_GetItem(hListView, &lvI))
  258. break;
  259. // determine URL type
  260. iURLTypeMatch = DetermineURLType(prgURLParsing, iURLArrayLen, lvI.pszText);
  261. if (iURLTypeMatch == -1) // no match
  262. continue;
  263. hr = ContractDisplayString(
  264. lvI.pszText,
  265. &pszContracted);
  266. // determine check state
  267. if (!ListView_GetCheckState(hListView, lvI.iItem))
  268. {
  269. // item not checked! add '-'
  270. fCheck = FALSE;
  271. }
  272. // alloc enough to hold existing, plus new [-]"string\0", plus \0 we'll tack on end of string
  273. DWORD dwAllocBytes = ((rgchszzEntries[iURLTypeMatch] + wcslen(pszContracted) + 2) * sizeof(WCHAR)) + (fCheck ? 0 : sizeof(WCHAR));
  274. if (NULL == rgszzEntries[iURLTypeMatch])
  275. {
  276. pszTmp = (LPWSTR)LocalAlloc(LMEM_FIXED, dwAllocBytes);
  277. }
  278. else
  279. {
  280. pszTmp = (LPWSTR)LocalReAlloc(
  281. rgszzEntries[iURLTypeMatch],
  282. dwAllocBytes,
  283. LMEM_MOVEABLE);
  284. }
  285. if (NULL == pszTmp)
  286. {
  287. // leave ppszzEntries as valid as it already is, try to recover
  288. break;
  289. }
  290. rgszzEntries[iURLTypeMatch] = pszTmp; // assign new mem to rgszz; meanwhile, pszTmp is shorthand
  291. DWORD chTmp = rgchszzEntries[iURLTypeMatch]; // temp assign
  292. if (!fCheck)
  293. {
  294. pszTmp[chTmp++] = L'-'; // item not checked
  295. }
  296. wcscpy(&pszTmp[chTmp], pszContracted);
  297. chTmp += wcslen(pszContracted)+1; // skip string\0
  298. pszTmp[chTmp] = L'\0'; // double NULL, don't count in rgchszzEntries
  299. // reassign chTmp to rgchszzEntries[iURLTypeMatch]
  300. rgchszzEntries[iURLTypeMatch] = chTmp;
  301. // clean up
  302. if (pszContracted)
  303. LocalFree(pszContracted);
  304. pszContracted = NULL;
  305. // next listbox entry!
  306. }
  307. // done, now commit all URL types to registry
  308. for (iURLTypeMatch=0; iURLTypeMatch<iURLArrayLen; iURLTypeMatch++)
  309. {
  310. hr = RegSetValueEx(
  311. hkeyStorage,
  312. prgURLParsing[iURLTypeMatch].szRegEntries,
  313. 0,
  314. REG_MULTI_SZ,
  315. (BYTE *) (NULL == rgszzEntries[iURLTypeMatch]?
  316. L"\0\0" : rgszzEntries[iURLTypeMatch]),
  317. (NULL == rgszzEntries[iURLTypeMatch]?
  318. 2 : rgchszzEntries[iURLTypeMatch] + 1) *
  319. sizeof(WCHAR)); // now add 2nd '\0'
  320. // Zero
  321. if (rgszzEntries[iURLTypeMatch])
  322. {
  323. LocalFree(rgszzEntries[iURLTypeMatch]);
  324. rgszzEntries[iURLTypeMatch] = NULL;
  325. rgchszzEntries[iURLTypeMatch] = 0;
  326. }
  327. if (hr != ERROR_SUCCESS)
  328. {
  329. //ASSERT(!"RegSetValueEx error!");
  330. continue;
  331. }
  332. }
  333. hr = S_OK;
  334. Ret:
  335. if (rgchszzEntries)
  336. LocalFree(rgchszzEntries);
  337. if (rgszzEntries)
  338. LocalFree(rgszzEntries);
  339. if (pszContracted)
  340. LocalFree(pszContracted);
  341. return hr;
  342. }
  343. HRESULT PopulateListView(
  344. HWND hListView,
  345. HKEY hkeyStorage,
  346. PCERTSVR_URL_PARSING prgURLParsing,
  347. DWORD cURLParsingEntries,
  348. DWORD dwEnableFlags)
  349. {
  350. HRESULT hr;
  351. LPWSTR pwszzMultiString = NULL, psz;
  352. for (DWORD i=0; i<cURLParsingEntries; i++)
  353. {
  354. DWORD cb=0, dwType;
  355. hr = RegQueryValueEx(
  356. hkeyStorage,
  357. prgURLParsing[i].szRegEntries,
  358. 0,
  359. &dwType,
  360. NULL,
  361. &cb);
  362. if ((hr != ERROR_SUCCESS) || (dwType != REG_MULTI_SZ) || (cb == 0))
  363. continue;
  364. pwszzMultiString = (LPWSTR)LocalAlloc(LMEM_FIXED, cb);
  365. if (NULL == pwszzMultiString)
  366. continue;
  367. hr = RegQueryValueEx(
  368. hkeyStorage,
  369. prgURLParsing[i].szRegEntries,
  370. 0,
  371. &dwType,
  372. (PBYTE)pwszzMultiString,
  373. &cb);
  374. if ((HRESULT) ERROR_SUCCESS != hr)
  375. {
  376. if (pwszzMultiString)
  377. LocalFree(pwszzMultiString);
  378. pwszzMultiString = NULL;
  379. continue;
  380. }
  381. // walk pwszzMultiString components
  382. for (psz = pwszzMultiString; (psz) && (psz[0] != '\0'); psz += wcslen(psz)+1)
  383. {
  384. BOOL fCheck = TRUE;
  385. LPWSTR szDisplayString;
  386. // if string starts with -, this is unchecked
  387. if (psz[0] == L'-')
  388. {
  389. fCheck = FALSE;
  390. psz++; // step past this char
  391. }
  392. // enable flags -- override
  393. if (prgURLParsing[i].dwEnableFlag != (dwEnableFlags & prgURLParsing[i].dwEnableFlag))
  394. fCheck = FALSE;
  395. hr = ExpandDisplayString(
  396. psz,
  397. &szDisplayString);
  398. if (hr != S_OK)
  399. continue;
  400. // add this sz
  401. AddStringToCheckList(
  402. hListView,
  403. szDisplayString, //psz,
  404. NULL,
  405. fCheck);
  406. LocalFree(szDisplayString);
  407. }
  408. if (pwszzMultiString)
  409. {
  410. LocalFree(pwszzMultiString);
  411. pwszzMultiString = NULL;
  412. }
  413. }
  414. hr = S_OK;
  415. //Ret:
  416. return hr;
  417. }
  418. BOOL OnDialogHelp(LPHELPINFO pHelpInfo, LPCTSTR szHelpFile, const DWORD rgzHelpIDs[])
  419. {
  420. if (rgzHelpIDs == NULL || szHelpFile == NULL)
  421. return TRUE;
  422. if (pHelpInfo != NULL && pHelpInfo->iContextType == HELPINFO_WINDOW)
  423. {
  424. // Display context help for a control
  425. WinHelp((HWND)pHelpInfo->hItemHandle, szHelpFile,
  426. HELP_WM_HELP, (ULONG_PTR)(LPVOID)rgzHelpIDs);
  427. }
  428. return TRUE;
  429. }
  430. BOOL OnDialogContextHelp(HWND hWnd, LPCTSTR szHelpFile, const DWORD rgzHelpIDs[])
  431. {
  432. if (rgzHelpIDs == NULL || szHelpFile == NULL)
  433. return TRUE;
  434. assert(IsWindow(hWnd));
  435. WinHelp(hWnd, szHelpFile, HELP_CONTEXTMENU, (ULONG_PTR)(LPVOID)rgzHelpIDs);
  436. return TRUE;
  437. }