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.

544 lines
19 KiB

  1. #include "item.h"
  2. extern HINSTANCE hInst;
  3. const BYTE RgbRC2_40[] = {
  4. 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x08, 0x2a, 0x86,
  5. 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02, 0x02, 0x01,
  6. 0x28
  7. };
  8. const int CbRC2_40 = sizeof(RgbRC2_40);
  9. const BYTE RgbRC2_128[] = {
  10. 0x30, 0x10,
  11. 0x30, 0xe,
  12. 0x6, 0x8, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x3, 0x2,
  13. 0x2, 0x2, 0x0, 0x80
  14. };
  15. const BYTE Rgb3DES[] = {
  16. 0x30, 0xc,
  17. 0x30, 0xa,
  18. 0x6, 0x8, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x3, 0x7
  19. };
  20. const BYTE RgbRC6[] = {
  21. 0x30, 0xc,
  22. 0x30, 0xa,
  23. 0x6, 0x8, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x3, 0x7f
  24. };
  25. const BYTE RgbSkipjack[] = {
  26. 0x30, 0xd,
  27. 0x30, 0xb,
  28. 0x6, 0x9, 0x60, 0x86, 0x48, 0x01, 0x65, 0x02, 0x01, 0x01, 0x04
  29. };
  30. struct {
  31. LPSTR szDesc;
  32. const BYTE * rgbAlg;
  33. DWORD cbAlg;
  34. } RgEncAlgs[] = {
  35. {"RC-2 40-bit", RgbRC2_40, sizeof(RgbRC2_40)},
  36. {"RC-2 64-bit", NULL, 0},
  37. {"RC-2 128-bit", RgbRC2_128, sizeof(RgbRC2_128)},
  38. {"DES", NULL, 0},
  39. {"Triple DES", Rgb3DES, sizeof(Rgb3DES)},
  40. {"RC-6", RgbRC6, sizeof(RgbRC6)},
  41. {"Skipjack", RgbSkipjack, sizeof(RgbSkipjack)},
  42. #define ALG_SKIPJACK 6
  43. };
  44. const int Enc_Alg_Max = sizeof(RgEncAlgs)/sizeof(RgEncAlgs[0]);
  45. ////////////////////////////////////////////////////////////////////////////////////
  46. HRESULT CEnvData::AddToMessage(DWORD * pulLayers, IMimeMessage * pmm, HWND hwnd)
  47. {
  48. CRYPT_ATTRIBUTE attr;
  49. DWORD cb;
  50. DWORD dwType = 0;
  51. FILETIME ft;
  52. HRESULT hr;
  53. IMimeBody * pmb = NULL;
  54. IMimeSecurity2 * pms2 = NULL;
  55. CItem * psd;
  56. BYTE rgb[50];
  57. CRYPT_ATTR_BLOB valTime;
  58. PROPVARIANT var;
  59. // Pull out the body interface to set security properties
  60. hr = pmm->BindToObject(HBODY_ROOT, IID_IMimeBody, (LPVOID *) &pmb);
  61. if (FAILED(hr)) goto exit;
  62. // Find out what security already exists
  63. hr = pmb->GetOption(OID_SECURITY_TYPE, &var);
  64. if (FAILED(hr)) goto exit;
  65. dwType = var.ulVal;
  66. // if any security, then we need to push on a new layer, all previous security
  67. // is now on the "y-security" layer and not on the hbody layer
  68. if (dwType & MST_THIS_ENCRYPT) {
  69. hr = pmm->QueryInterface(IID_IMimeSecurity2, (LPVOID *) &pms2);
  70. if (FAILED(hr)) goto exit;
  71. hr = pms2->Encode(hwnd, SEF_SENDERSCERTPROVIDED |
  72. SEF_ENCRYPTWITHNOSENDERCERT);
  73. if (FAILED(hr)) goto exit;
  74. pms2->Release(); pms2 = NULL;
  75. pmb->Release(); pmb = NULL;
  76. dwType = 0;
  77. hr = pmm->BindToObject(HBODY_ROOT, IID_IMimeBody, (LPVOID *) &pmb);
  78. if (FAILED(hr)) goto exit;
  79. }
  80. // We are going to put encryption on this layer
  81. dwType |= MST_THIS_ENCRYPT;
  82. // Security Type
  83. var.vt = VT_UI4;
  84. var.ulVal = dwType;
  85. hr = pmb->SetOption(OID_SECURITY_TYPE, &var);
  86. if (FAILED(hr)) goto exit;
  87. var.vt = VT_BLOB;
  88. var.blob.cbSize = RgEncAlgs[m_iAlg].cbAlg;
  89. var.blob.pBlobData = (LPBYTE) RgEncAlgs[m_iAlg].rgbAlg;
  90. hr = pmb->SetOption(OID_SECURITY_ALG_BULK, &var);
  91. if (FAILED(hr)) goto exit;
  92. var.vt = VT_UI4;
  93. var.ulVal = SEF_SENDERSCERTPROVIDED;
  94. hr = pmm->SetOption(OID_SECURITY_ENCODE_FLAGS, &var);
  95. if (FAILED(hr)) goto exit;
  96. for (psd = Head(); psd != NULL; psd = psd->Next()) {
  97. hr = psd->AddToMessage(pulLayers, pmm, hwnd);
  98. if (FAILED(hr)) goto exit;
  99. }
  100. if (m_fAttributes || m_fUnProtAttrib){
  101. hr = pmb->QueryInterface(IID_IMimeSecurity2, (LPVOID *) &pms2);
  102. if (FAILED(hr)) goto exit;
  103. }
  104. if (m_fAttributes) {
  105. GetSystemTimeAsFileTime(&ft);
  106. cb = sizeof(rgb);
  107. if (CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME,
  108. &ft, 0, 0, rgb, &cb)) {
  109. attr.pszObjId = szOID_RSA_signingTime;
  110. attr.cValue = 1;
  111. attr.rgValue = &valTime;
  112. valTime.pbData = rgb;
  113. valTime.cbData = cb;
  114. hr = pms2->SetAttribute(0, 0, SMIME_ATTRIBUTE_SET_UNPROTECTED, &attr);
  115. if (FAILED(hr)) goto exit;
  116. }
  117. }
  118. if (m_fUnProtAttrib && (m_szUnProtAttribOID != NULL) && (m_valUnProtAttrib.pbData != NULL)) {
  119. attr.pszObjId = m_szUnProtAttribOID;
  120. attr.cValue = 1;
  121. attr.rgValue = &m_valUnProtAttrib;
  122. hr = pms2->SetAttribute(0, 0, SMIME_ATTRIBUTE_SET_UNPROTECTED, &attr);
  123. if (FAILED(hr)) goto exit;
  124. }
  125. hr = S_OK;
  126. exit:
  127. if (pms2 != NULL) pms2->Release();
  128. if (pmb != NULL) pmb->Release();
  129. *pulLayers += 1;
  130. return hr;
  131. }
  132. /////////////////////////////////////////////////////////////////////////////////////////////
  133. HRESULT CEnvCertTrans::AddToMessage(DWORD * pulLayer, IMimeMessage * pmm,
  134. HWND hwnd)
  135. {
  136. DWORD cb;
  137. HRESULT hr;
  138. DWORD i;
  139. CRYPT_DATA_BLOB * pblob;
  140. PCERT_EXTENSION pext;
  141. IMimeBody * pmb = NULL;
  142. CMS_RECIPIENT_INFO * precipInfo = NULL;
  143. IMimeSecurity2 * psm = NULL;
  144. hr = pmm->BindToObject(HBODY_ROOT, IID_IMimeBody, (LPVOID *) &pmb);
  145. if (FAILED(hr)) goto exit;
  146. hr = pmb->QueryInterface(IID_IMimeSecurity2, (LPVOID*) &psm);
  147. if (FAILED(hr)) goto exit;
  148. precipInfo = (CMS_RECIPIENT_INFO *) malloc(sizeof(*precipInfo)*m_cCerts);
  149. if (precipInfo == NULL) goto exit;
  150. memset(precipInfo, 0, sizeof(*precipInfo)*m_cCerts);
  151. for (i=0; i<m_cCerts; i++) {
  152. precipInfo[i].dwRecipientType = CMS_RECIPIENT_INFO_TYPE_UNKNOWN;
  153. precipInfo[i].pccert = m_rgpccert[i];
  154. if (m_fUseSKI) {
  155. pext = CertFindExtension(szOID_SUBJECT_KEY_IDENTIFIER,
  156. m_rgpccert[i]->pCertInfo->cExtension,
  157. m_rgpccert[i]->pCertInfo->rgExtension);
  158. if (pext == NULL) {
  159. continue;
  160. }
  161. if (!CryptDecodeObjectEx(X509_ASN_ENCODING,
  162. szOID_SUBJECT_KEY_IDENTIFIER,
  163. pext->Value.pbData, pext->Value.cbData,
  164. CRYPT_DECODE_ALLOC_FLAG,
  165. NULL, &pblob, &cb)) {
  166. continue;
  167. }
  168. precipInfo[i].dwU3 = CMS_RECIPIENT_INFO_KEYID_KEY_ID;
  169. precipInfo[i].u3.KeyId.pbData = (LPBYTE) malloc(pblob->cbData);
  170. memcpy(precipInfo[i].u3.KeyId.pbData, pblob->pbData, pblob->cbData);
  171. precipInfo[i].u3.KeyId.cbData = pblob->cbData;
  172. LocalFree(pblob);
  173. }
  174. }
  175. hr = psm->AddRecipient(0, m_cCerts, precipInfo);
  176. if (FAILED(hr)) goto exit;
  177. for (i=0; i<m_cCerts; i++) {
  178. if (precipInfo[i].dwU3 == CMS_RECIPIENT_INFO_KEYID_KEY_ID) {
  179. free(precipInfo[i].u3.KeyId.pbData);
  180. }
  181. }
  182. hr = S_OK;
  183. exit:
  184. if (psm != NULL) psm->Release();
  185. if (pmb != NULL) pmb->Release();
  186. if (precipInfo != NULL) free(precipInfo);
  187. return hr;
  188. }
  189. /////////////////////////////////////////////////////////////////////////////////////////////
  190. HRESULT CEnvCertAgree::AddToMessage(DWORD * pulLayer, IMimeMessage * pmm,
  191. HWND hwnd)
  192. {
  193. DWORD cCerts;
  194. HCRYPTPROV hprov = NULL;
  195. HRESULT hr;
  196. DWORD i;
  197. IMimeBody * pmb = NULL;
  198. CMS_RECIPIENT_INFO * precipInfo = NULL;
  199. IMimeSecurity2 * psm = NULL;
  200. PROPVARIANT var;
  201. hr = pmm->BindToObject(HBODY_ROOT, IID_IMimeBody, (LPVOID *) &pmb);
  202. if (FAILED(hr)) goto exit;
  203. hr = pmb->QueryInterface(IID_IMimeSecurity2, (LPVOID*) &psm);
  204. if (FAILED(hr)) goto exit;
  205. precipInfo = (CMS_RECIPIENT_INFO *) malloc(sizeof(*precipInfo)*m_cCerts);
  206. if (precipInfo == NULL) goto exit;
  207. memset(precipInfo, 0, sizeof(*precipInfo)*m_cCerts);
  208. if (m_cCerts == 0) {
  209. hr = E_FAIL;
  210. goto exit;
  211. }
  212. if (strcmp(m_rgpccert[0]->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId,
  213. szOID_INFOSEC_keyExchangeAlgorithm) == 0) {
  214. DWORD cb;
  215. PCRYPT_KEY_PROV_INFO pInfo;
  216. //
  217. // Get the parameters from the key
  218. if (!CertGetCertificateContextProperty(m_rgpccert[0],
  219. CERT_KEY_PROV_INFO_PROP_ID,
  220. NULL, &cb)) {
  221. hr = E_FAIL;
  222. goto exit;
  223. }
  224. pInfo = (PCRYPT_KEY_PROV_INFO) malloc(cb);
  225. if (!CertGetCertificateContextProperty(m_rgpccert[0],
  226. CERT_KEY_PROV_INFO_PROP_ID,
  227. pInfo, &cb)) {
  228. hr = E_FAIL;
  229. goto exit;
  230. }
  231. // Setup originator info
  232. if (!CryptAcquireContextW(&hprov, pInfo->pwszContainerName,
  233. pInfo->pwszProvName, pInfo->dwProvType, 0)) {
  234. hr = E_FAIL;
  235. goto exit;
  236. }
  237. var.vt = VT_UI4;
  238. var.ulVal = (DWORD) hprov;
  239. hr = pmb->SetOption(OID_SECURITY_HCRYPTPROV, &var);
  240. if (FAILED(hr)) goto exit;
  241. for (i=1; i<m_cCerts; i++) {
  242. precipInfo[i-1].dwRecipientType = CMS_RECIPIENT_INFO_TYPE_KEYAGREE;
  243. precipInfo[i-1].pccert = m_rgpccert[i];
  244. precipInfo[i-1].KeyEncryptionAlgorithm.pszObjId =
  245. szOID_INFOSEC_keyExchangeAlgorithm;
  246. precipInfo[i-1].dwU1 = CMS_RECIPIENT_INFO_PUBKEY_STATIC_KEYAGREE;
  247. precipInfo[i-1].u1.u4.hprov = hprov;
  248. precipInfo[i-1].u1.u4.dwKeySpec = AT_KEYEXCHANGE;
  249. precipInfo[i-1].u1.u4.senderCertId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  250. precipInfo[i-1].u1.u4.senderCertId.IssuerSerialNumber.Issuer = m_rgpccert[0]->pCertInfo->Issuer;
  251. precipInfo[i-1].u1.u4.senderCertId.IssuerSerialNumber.SerialNumber = m_rgpccert[0]->pCertInfo->SerialNumber;
  252. precipInfo[i-1].u1.u4.SubjectPublicKey = m_rgpccert[i]->pCertInfo->SubjectPublicKeyInfo.PublicKey;
  253. precipInfo[i-1].dwU3 = CMS_RECIPIENT_INFO_KEYID_ISSUERSERIAL;
  254. precipInfo[i-1].u3.IssuerSerial.Issuer = m_rgpccert[i]->pCertInfo->Issuer;
  255. precipInfo[i-1].u3.IssuerSerial.SerialNumber = m_rgpccert[i]->pCertInfo->SerialNumber;
  256. }
  257. hprov = NULL;
  258. cCerts = m_cCerts - 1;
  259. }
  260. else {
  261. for (i=0; i<m_cCerts; i++) {
  262. precipInfo[i].dwRecipientType = CMS_RECIPIENT_INFO_TYPE_UNKNOWN;
  263. precipInfo[i].pccert = m_rgpccert[i];
  264. }
  265. cCerts = m_cCerts;
  266. }
  267. hr = psm->AddRecipient(0, cCerts, precipInfo);
  268. if (FAILED(hr)) goto exit;
  269. hr = S_OK;
  270. exit:
  271. if (hprov != NULL) CryptReleaseContext(hprov, 0);
  272. if (psm != NULL) psm->Release();
  273. if (pmb != NULL) pmb->Release();
  274. if (precipInfo != NULL) free(precipInfo);
  275. return hr;
  276. }
  277. /////////////////////////////////////////////////////////////////////////////////////////////
  278. BOOL CALLBACK EncDataDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  279. {
  280. DWORD i;
  281. DWORD iSel;
  282. static CEnvData * ped = NULL;
  283. CHAR rgch[300];
  284. switch (msg) {
  285. case WM_INITDIALOG:
  286. for (i=0; i<sizeof(RgEncAlgs)/sizeof(RgEncAlgs[0]); i++) {
  287. if (RgEncAlgs[i].rgbAlg != NULL) {
  288. iSel = SendDlgItemMessage(hdlg, IDC_EIC_ALG_SELECT, CB_ADDSTRING,
  289. 0, (LPARAM) RgEncAlgs[i].szDesc);
  290. SendDlgItemMessage(hdlg, IDC_EIC_ALG_SELECT, CB_SETITEMDATA,
  291. iSel, i);
  292. }
  293. }
  294. SendDlgItemMessage(hdlg, IDC_EIC_ALG_SELECT, CB_SETCURSEL, 0, 0);
  295. SendDlgItemMessage(hdlg, IDC_EIC_FORCE, BM_SETCHECK, 1, 0);
  296. break;
  297. case UM_SET_DATA:
  298. ped = (CEnvData *) lParam;
  299. // Fill in the dialog
  300. if (ped != NULL) {
  301. SendDlgItemMessage(hdlg, IDC_EIC_ALG_SELECT, CB_SETCURSEL,
  302. ped->GetAlg(), 0);
  303. }
  304. SendDlgItemMessage(hdlg, IDC_EIC_ATTRIBUTES, BM_SETCHECK,
  305. ((ped != NULL) && (ped->m_fAttributes)), 0);
  306. SendDlgItemMessage(hdlg, IDC_EIC_UNPROTATTRIB, BM_SETCHECK,
  307. ((ped != NULL) && (ped->m_fUnProtAttrib)), 0);
  308. break;
  309. case WM_COMMAND:
  310. switch (wParam) {
  311. case MAKELONG(IDC_EIC_ALG_SELECT, CBN_SELCHANGE):
  312. i = SendDlgItemMessage(hdlg, IDC_EIC_ALG_SELECT, CB_GETCURSEL, 0, 0);
  313. ped->SetAlg(SendDlgItemMessage(hdlg, IDC_EIC_ALG_SELECT,
  314. CB_GETITEMDATA, i, 0));
  315. break;
  316. case MAKELONG(IDC_EIC_ATTRIBUTES, BN_CLICKED):
  317. ped->m_fAttributes = SendDlgItemMessage(hdlg, IDC_EIC_ATTRIBUTES,
  318. BM_GETCHECK, 0, 0);
  319. break;
  320. case MAKELONG(IDC_EIC_UNPROTATTRIB, BN_CLICKED):
  321. ped->m_fUnProtAttrib = SendDlgItemMessage(hdlg, IDC_EIC_UNPROTATTRIB, BM_GETCHECK,
  322. 0, 0);
  323. break;
  324. case IDC_EIC_DO_UNPROTATTRIB:
  325. DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ATTRIB_CREATE), hdlg,
  326. UnProtAttribCreateDlgProc, (LPARAM) ped);
  327. break;
  328. default:
  329. return FALSE;
  330. }
  331. break;
  332. default:
  333. return FALSE;
  334. }
  335. return TRUE;
  336. }
  337. BOOL CALLBACK EncDataComposeDlgProc(CEncItem ** ppei, HWND hdlg, UINT msg,
  338. WPARAM wParam, LPARAM lParam, int iFilter)
  339. {
  340. DWORD i;
  341. DWORD i1;
  342. PCCERT_CONTEXT pccert;
  343. char rgch[256];
  344. switch (msg) {
  345. case WM_INITDIALOG:
  346. break;
  347. case UM_SET_DATA:
  348. // Back load from dialog
  349. if (*ppei != NULL) {
  350. if ((*ppei)->m_rgpccert != NULL) {
  351. for (i=0; i<(*ppei)->m_cCerts; i++) {
  352. CertFreeCertificateContext((*ppei)->m_rgpccert[i]);
  353. }
  354. free((*ppei)->m_rgpccert);
  355. (*ppei)->m_rgpccert = 0;
  356. (*ppei)->m_cCerts = 0;
  357. }
  358. i1 = SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_GETCOUNT, 0, 0);
  359. (*ppei)->m_rgpccert = (PCCERT_CONTEXT *) malloc(sizeof(PCCERT_CONTEXT)*i1);
  360. for (i=0; i<i1; i++) {
  361. (*ppei)->m_rgpccert[i] = (PCCERT_CONTEXT)
  362. SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_GETITEMDATA, i, 0);
  363. }
  364. (*ppei)->m_cCerts = i1;
  365. SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_RESETCONTENT, 0, 0);
  366. }
  367. Assert(SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_GETCOUNT, 0, 0) == 0);
  368. *ppei = (CEncItem *) lParam;
  369. // Fill in the dialog
  370. if (*ppei != NULL) {
  371. for (i=0; i<(*ppei)->m_cCerts; i++) {
  372. GetFriendlyNameOfCertA((*ppei)->m_rgpccert[i], rgch, sizeof(rgch));
  373. i1 = SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_ADDSTRING, 0, (LPARAM) rgch);
  374. SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_SETITEMDATA, i1,
  375. (LPARAM) CertDuplicateCertificateContext((*ppei)->m_rgpccert[i]));
  376. }
  377. }
  378. SendDlgItemMessage(hdlg, IDC_ETC_LIST, BM_SETCHECK,
  379. (((*ppei) != NULL) && ((*ppei)->m_fUseSKI)), 0);
  380. break;
  381. case WM_DESTROY:
  382. i1 = SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_GETCOUNT, 0, 0);
  383. for (i=0; i<i1; i++) {
  384. CertFreeCertificateContext((PCCERT_CONTEXT)
  385. SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_GETITEMDATA, i, 0));
  386. }
  387. break;
  388. case WM_COMMAND:
  389. switch (wParam) {
  390. case IDC_ETC_ADD_CERT:
  391. pccert = NULL;
  392. if (DoCertDialog(hdlg, "Choose Enryption Certificate To Add",
  393. (*ppei)->GetAllStore(), &pccert, iFilter)) {
  394. GetFriendlyNameOfCertA(pccert, rgch, sizeof(rgch));
  395. i1 = SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_ADDSTRING, 0, (LPARAM) rgch);
  396. SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_SETITEMDATA, i1,
  397. (LPARAM) pccert);
  398. }
  399. break;
  400. case IDC_ETC_DEL_CERT:
  401. i = SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_GETCURSEL, 0, 0);
  402. if (i != LB_ERR) {
  403. CertFreeCertificateContext((PCCERT_CONTEXT)
  404. SendDlgItemMessage(hdlg, IDC_ETC_LIST, LB_GETITEMDATA, i, 0));
  405. }
  406. break;
  407. case MAKELONG(IDC_ETC_SKI, BN_CLICKED):
  408. (*ppei)->m_fUseSKI = SendDlgItemMessage(hdlg, IDC_ETC_SKI, BM_GETCHECK,
  409. 0, 0);
  410. break;
  411. default:
  412. return FALSE;
  413. }
  414. break;
  415. default:
  416. return FALSE;
  417. }
  418. return TRUE;
  419. }
  420. BOOL CALLBACK EncTransCompDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  421. {
  422. static CEncItem * pei = NULL;
  423. return EncDataComposeDlgProc(&pei, hdlg, msg, wParam, lParam, FILTER_RSA_KEYEX);
  424. }
  425. BOOL CALLBACK EncAgreeCompDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  426. {
  427. DWORD dwFilter = FILTER_DH_KEYEX;
  428. static CEncItem * pei = NULL;
  429. if (pei != NULL) {
  430. if (pei->GetParent()->GetAlg() == ALG_SKIPJACK) {
  431. dwFilter = FILTER_KEA_KEYEX;
  432. }
  433. }
  434. return EncDataComposeDlgProc(&pei, hdlg, msg, wParam, lParam, dwFilter);
  435. }
  436. BOOL CALLBACK EncInfoReadDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  437. {
  438. DWORD i;
  439. switch (msg) {
  440. case WM_INITDIALOG:
  441. break;
  442. default:
  443. return FALSE;
  444. }
  445. return TRUE;
  446. }