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.

680 lines
20 KiB

  1. #include "cstore.hxx"
  2. // set property routines do not do any allocations.
  3. // get properties have 2 different sets of routines
  4. // 1. in which there is no allocation taking place
  5. // and the buffers are freed when the ds data structures
  6. // are freed.
  7. // 2. Allocation takes place and these should be used for
  8. // data that needs to be returned back to the clients.
  9. void FreeAttr(ADS_ATTR_INFO attr)
  10. {
  11. CoTaskMemFree(attr.pADsValues);
  12. }
  13. // Note: None of these APIs copies anything into their own buffers.
  14. // It allocates a buffer for adsvalues though.
  15. // packing a property's value into a attribute structure
  16. // for sending in with a create/modify.
  17. void PackStrArrToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty,
  18. WCHAR **pszAttr, DWORD num)
  19. {
  20. DWORD i;
  21. attr->pszAttrName = szProperty;
  22. attr->dwNumValues = num;
  23. if (num)
  24. attr->dwControlCode = ADS_ATTR_UPDATE;
  25. else
  26. attr->dwControlCode = ADS_ATTR_CLEAR;
  27. attr->dwADsType = ADSTYPE_DN_STRING;
  28. attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
  29. if (!(attr->pADsValues))
  30. return; // BUGBUG:: return the hresult.
  31. for (i = 0; i < num; i++) {
  32. attr->pADsValues[i].dwType = ADSTYPE_DN_STRING;
  33. attr->pADsValues[i].DNString = pszAttr[i];
  34. }
  35. }
  36. void PackDWArrToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, DWORD *pAttr, DWORD num)
  37. {
  38. DWORD i;
  39. attr->pszAttrName = szProperty;
  40. attr->dwNumValues = num;
  41. if (num)
  42. attr->dwControlCode = ADS_ATTR_UPDATE;
  43. else
  44. attr->dwControlCode = ADS_ATTR_CLEAR;
  45. attr->dwADsType = ADSTYPE_INTEGER;
  46. attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
  47. if (!(attr->pADsValues))
  48. return; // BUGBUG:: return the hresult.
  49. for (i = 0; i < num; i++) {
  50. attr->pADsValues[i].dwType = ADSTYPE_INTEGER;
  51. attr->pADsValues[i].Integer = pAttr[i];
  52. }
  53. }
  54. void PackGUIDArrToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, GUID *pAttr, DWORD num)
  55. {
  56. DWORD i;
  57. attr->pszAttrName = szProperty;
  58. attr->dwNumValues = num;
  59. if (num)
  60. attr->dwControlCode = ADS_ATTR_UPDATE;
  61. else
  62. attr->dwControlCode = ADS_ATTR_CLEAR;
  63. attr->dwADsType = ADSTYPE_OCTET_STRING;
  64. attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
  65. if (!(attr->pADsValues))
  66. return; // BUGBUG:: return the hresult.
  67. for (i = 0; i < num; i++) {
  68. attr->pADsValues[i].dwType = ADSTYPE_OCTET_STRING;
  69. attr->pADsValues[i].OctetString.dwLength = sizeof(GUID);
  70. attr->pADsValues[i].OctetString.lpValue = (unsigned char *)(pAttr+i);
  71. }
  72. }
  73. void PackBinToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, BYTE *pAttr, DWORD sz)
  74. {
  75. attr->pszAttrName = szProperty;
  76. attr->dwNumValues = 1;
  77. attr->dwControlCode = ADS_ATTR_UPDATE;
  78. attr->dwADsType = ADSTYPE_OCTET_STRING;
  79. attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE));
  80. if (!(attr->pADsValues))
  81. return; // BUGBUG:: return the hresult.
  82. attr->pADsValues[0].dwType = ADSTYPE_OCTET_STRING;
  83. attr->pADsValues[0].OctetString.dwLength = sz;
  84. attr->pADsValues[0].OctetString.lpValue = pAttr;
  85. }
  86. void PackStrToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, WCHAR *szAttr)
  87. {
  88. if (szAttr)
  89. PackStrArrToAttr(attr, szProperty, &szAttr, 1);
  90. else
  91. PackStrArrToAttr(attr, szProperty, &szAttr, 0);
  92. }
  93. void PackDWToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, DWORD Attr)
  94. {
  95. PackDWArrToAttr(attr, szProperty, &Attr, 1);
  96. }
  97. // passing in a pointer to GUID which is passed down into the LDAP structure.
  98. void PackGUIDToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, GUID *pAttr)
  99. {
  100. PackGUIDArrToAttr(attr, szProperty, pAttr, 1);
  101. }
  102. // returns the attribute corresp. to a given property.
  103. DWORD GetPropertyFromAttr(ADS_ATTR_INFO *pattr, DWORD cNum, WCHAR *szProperty)
  104. {
  105. DWORD i;
  106. for (i = 0; i < cNum; i++)
  107. if (_wcsicmp(pattr[i].pszAttrName, szProperty) == 0)
  108. break;
  109. return i;
  110. }
  111. HRESULT GetCategoryLocaleDesc(LPOLESTR *pdesc, ULONG cdesc, LCID *plcid,
  112. LPOLESTR szDescription)
  113. {
  114. LCID plgid;
  115. LPOLESTR ptr;
  116. szDescription[0] = L'\0';
  117. if (!cdesc)
  118. return E_FAIL; // CAT_E_NODESCRIPTION;
  119. // Try locale passed in
  120. if (FindDescription(pdesc, cdesc, plcid, szDescription, 0))
  121. return S_OK;
  122. // Get default sublang local
  123. plgid = PRIMARYLANGID((WORD)*plcid);
  124. *plcid = MAKELCID(MAKELANGID(plgid, SUBLANG_DEFAULT), SORT_DEFAULT);
  125. if (FindDescription(pdesc, cdesc, plcid, szDescription, 0))
  126. return S_OK;
  127. // Get matching lang id
  128. if (FindDescription(pdesc, cdesc, plcid, szDescription, 1))
  129. return S_OK;
  130. // Get User Default
  131. *plcid = GetUserDefaultLCID();
  132. if (FindDescription(pdesc, cdesc, plcid, szDescription, 0))
  133. return S_OK;
  134. // Get System Default
  135. *plcid = GetUserDefaultLCID();
  136. if (FindDescription(pdesc, cdesc, plcid, szDescription, 0))
  137. return S_OK;
  138. // Get the first one
  139. *plcid = wcstoul(pdesc[0], &ptr, 16);
  140. if (szDescription)
  141. {
  142. if ((ptr) && (wcslen(ptr) >= (CAT_DESC_DELIM_LEN+2)))
  143. wcscpy(szDescription, (ptr+CAT_DESC_DELIM_LEN+2));
  144. else
  145. szDescription = L'\0';
  146. }
  147. return S_OK;
  148. }
  149. //-------------------------------------------
  150. // Returns the description corresp. to a LCID
  151. // desc: list of descs+lcid
  152. // cdesc: number of elements.
  153. // plcid: the lcid in/out
  154. // szDescription:description returned.
  155. // GetPrimary: Match only the primary.
  156. //---------------------------------------
  157. ULONG FindDescription(LPOLESTR *desc, ULONG cdesc, LCID *plcid, LPOLESTR szDescription, BOOL GetPrimary)
  158. {
  159. ULONG i;
  160. LCID newlcid;
  161. LPOLESTR ptr;
  162. for (i = 0; i < cdesc; i++)
  163. {
  164. newlcid = wcstoul(desc[i], &ptr, 16); // to be changed
  165. // error to be checked.
  166. if ((newlcid == *plcid) || ((GetPrimary) &&
  167. (PRIMARYLANGID((WORD)*plcid) == PRIMARYLANGID(LANGIDFROMLCID(newlcid)))))
  168. {
  169. if (szDescription)
  170. {
  171. if ((ptr) && (wcslen(ptr) >= (CAT_DESC_DELIM_LEN+2)))
  172. wcscpy(szDescription, (ptr+CAT_DESC_DELIM_LEN+2));
  173. else
  174. szDescription = L'\0';
  175. }
  176. if (GetPrimary)
  177. *plcid = newlcid;
  178. return i+1;
  179. }
  180. }
  181. return 0;
  182. }
  183. DWORD NumDigits10(DWORD Value)
  184. {
  185. DWORD ret = 0;
  186. for (ret = 0; Value != 0; ret++)
  187. Value = Value/10;
  188. return ret;
  189. }
  190. void ReportEventCS(HRESULT ErrorCode, HRESULT ExtendedErrorCode, LPOLESTR szContainerName)
  191. {
  192. WCHAR szErrCode[16];
  193. LPCTSTR Msg[2];
  194. HANDLE hEventLogHandle;
  195. Msg[0] = szContainerName;
  196. Msg[1] = szErrCode;
  197. wsprintf(szErrCode, L"0x%x", ExtendedErrorCode);
  198. hEventLogHandle = RegisterEventSource(NULL, CLASSSTORE_EVENT_SOURCE);
  199. if (!hEventLogHandle)
  200. {
  201. #if DBG
  202. // Don't want to call call CSDBGPrint
  203. WCHAR Msg[_MAX_PATH];
  204. wsprintf(Msg, L"CSTORE: ReportEventCS: Couldn't open event log. Error returned 0x%x\n", GetLastError());
  205. OutputDebugString(Msg);
  206. #endif // DBG
  207. return;
  208. }
  209. switch (ErrorCode) {
  210. case CS_E_INVALID_VERSION:
  211. ReportEvent(hEventLogHandle,
  212. EVENTLOG_ERROR_TYPE,
  213. 0,
  214. EVENT_CS_INVALID_VERSION,
  215. NULL,
  216. 2,
  217. 0,
  218. Msg,
  219. NULL
  220. );
  221. break;
  222. case CS_E_NETWORK_ERROR:
  223. ReportEvent(hEventLogHandle,
  224. EVENTLOG_ERROR_TYPE,
  225. 0,
  226. EVENT_CS_NETWORK_ERROR,
  227. NULL,
  228. 2,
  229. 0,
  230. Msg,
  231. NULL
  232. );
  233. break;
  234. case CS_E_INVALID_PATH:
  235. ReportEvent(hEventLogHandle,
  236. EVENTLOG_ERROR_TYPE,
  237. 0,
  238. EVENT_CS_INVALID_PATH,
  239. NULL,
  240. 2,
  241. 0,
  242. Msg,
  243. NULL
  244. );
  245. break;
  246. case CS_E_SCHEMA_MISMATCH:
  247. ReportEvent(hEventLogHandle,
  248. EVENTLOG_ERROR_TYPE,
  249. 0,
  250. EVENT_CS_SCHEMA_MISMATCH,
  251. NULL,
  252. 2,
  253. 0,
  254. Msg,
  255. NULL
  256. );
  257. break;
  258. case CS_E_INTERNAL_ERROR:
  259. ReportEvent(hEventLogHandle,
  260. EVENTLOG_ERROR_TYPE,
  261. 0,
  262. EVENT_CS_INTERNAL_ERROR,
  263. NULL,
  264. 2,
  265. 0,
  266. Msg,
  267. NULL
  268. );
  269. break;
  270. }
  271. BOOL bDeregistered;
  272. bDeregistered = DeregisterEventSource(hEventLogHandle);
  273. if (!bDeregistered)
  274. {
  275. #if DBG
  276. // Don't want to call call CSDBGPrint
  277. WCHAR Msg[_MAX_PATH];
  278. wsprintf(Msg, L"CSTORE: ReportEventCS: Couldn't Deregister event log. Error returned 0x%x\n", GetLastError());
  279. OutputDebugString(Msg);
  280. #endif // DBG
  281. }
  282. }
  283. // remapping Error Codes returned by LDAP to reasonable class store errors.
  284. //
  285. HRESULT RemapErrorCode(HRESULT ErrorCode, LPOLESTR m_szContainerName)
  286. {
  287. HRESULT RetCode;
  288. if (SUCCEEDED(ErrorCode))
  289. return S_OK;
  290. switch (ErrorCode)
  291. {
  292. //
  293. // All kinds of failures due to ObjectNotFound
  294. // due to non-existence of object OR
  295. // non-existent container OR
  296. // invalid path specification
  297. // Other than Access Denails
  298. //
  299. case HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT):
  300. case HRESULT_FROM_WIN32(ERROR_DS_NO_RESULTS_RETURNED): // understand what causes this
  301. case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_NOT_FOUND): // -do-
  302. RetCode = CS_E_OBJECT_NOTFOUND; // which object - specific error
  303. break;
  304. case HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS):
  305. case HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS):
  306. case E_ADS_OBJECT_EXISTS:
  307. RetCode = CS_E_OBJECT_ALREADY_EXISTS;
  308. break;
  309. //
  310. // The following errors should not be expected normally.
  311. // Class Store schema mismatched should be handled correctly.
  312. // Errors below may ONLY occur for corrupted data OR out-of-band changes
  313. // to a Class Store content.
  314. case E_ADS_CANT_CONVERT_DATATYPE:
  315. case E_ADS_SCHEMA_VIOLATION:
  316. case HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE):
  317. case HRESULT_FROM_WIN32(ERROR_DS_CONSTRAINT_VIOLATION):
  318. RetCode = CS_E_SCHEMA_MISMATCH;
  319. break;
  320. //
  321. // Any kinds of Access or Auth Denial
  322. // return ACCESS_DENIED
  323. //
  324. case HRESULT_FROM_WIN32(ERROR_DS_AUTH_METHOD_NOT_SUPPORTED):
  325. case HRESULT_FROM_WIN32(ERROR_DS_STRONG_AUTH_REQUIRED):
  326. case HRESULT_FROM_WIN32(ERROR_DS_CONFIDENTIALITY_REQUIRED):
  327. case HRESULT_FROM_WIN32(ERROR_INVALID_PASSWORD):
  328. case HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED):
  329. case HRESULT_FROM_WIN32(ERROR_DS_AUTH_UNKNOWN):
  330. RetCode = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  331. break;
  332. case E_ADS_BAD_PATHNAME:
  333. case HRESULT_FROM_WIN32(ERROR_DS_INVALID_ATTRIBUTE_SYNTAX): // this is wrong
  334. RetCode = CS_E_INVALID_PATH;
  335. break;
  336. //
  337. // Out of Memory
  338. //
  339. case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
  340. case HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY):
  341. RetCode = E_OUTOFMEMORY;
  342. break;
  343. //
  344. // Any DNS, DS or Network failures
  345. //
  346. case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_RESOLVING):
  347. case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_NOT_UNIQUE):
  348. case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_NO_MAPPING):
  349. case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_DOMAIN_ONLY):
  350. case HRESULT_FROM_WIN32(ERROR_DS_TIMELIMIT_EXCEEDED):
  351. case HRESULT_FROM_WIN32(ERROR_DS_BUSY):
  352. case HRESULT_FROM_WIN32(ERROR_DS_UNAVAILABLE):
  353. case HRESULT_FROM_WIN32(ERROR_DS_UNWILLING_TO_PERFORM):
  354. case HRESULT_FROM_WIN32(ERROR_TIMEOUT):
  355. case HRESULT_FROM_WIN32(ERROR_CONNECTION_REFUSED):
  356. case HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN):
  357. case HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN):
  358. RetCode = CS_E_NETWORK_ERROR;
  359. break;
  360. case HRESULT_FROM_WIN32(ERROR_DS_ADMIN_LIMIT_EXCEEDED):
  361. RetCode = CS_E_ADMIN_LIMIT_EXCEEDED;
  362. break;
  363. case CS_E_OBJECT_NOTFOUND:
  364. case CS_E_OBJECT_ALREADY_EXISTS:
  365. case CS_E_INVALID_VERSION:
  366. case CS_E_PACKAGE_NOTFOUND:
  367. RetCode = ErrorCode;
  368. break;
  369. case E_INVALIDARG:
  370. case ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS:
  371. RetCode = E_INVALIDARG;
  372. break;
  373. default:
  374. RetCode = CS_E_INTERNAL_ERROR;
  375. }
  376. CSDBGPrint((L"Error Code 0x%x remapped to 0x%x\n", ErrorCode, RetCode));
  377. if ((RetCode == CS_E_INVALID_PATH) ||
  378. (RetCode == CS_E_NETWORK_ERROR) ||
  379. (RetCode == CS_E_INVALID_VERSION) ||
  380. (RetCode == CS_E_SCHEMA_MISMATCH) ||
  381. (RetCode == CS_E_INTERNAL_ERROR))
  382. ReportEventCS(RetCode, ErrorCode, m_szContainerName);
  383. return RetCode;
  384. }
  385. // These functions are used to delete a single value from a
  386. // multivalued property or append to a multivalued property
  387. void PackStrArrToAttrEx(ADS_ATTR_INFO *attr, WCHAR *szProperty, WCHAR **pszAttr, DWORD num,
  388. BOOL APPEND)
  389. {
  390. DWORD i;
  391. attr->pszAttrName = szProperty;
  392. attr->dwNumValues = num;
  393. if (APPEND)
  394. attr->dwControlCode = ADS_ATTR_APPEND;
  395. else
  396. attr->dwControlCode = ADS_ATTR_DELETE;
  397. attr->dwADsType = ADSTYPE_DN_STRING;
  398. attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
  399. if (!(attr->pADsValues))
  400. return; // BUGBUG:: return the hresult.
  401. for (i = 0; i < num; i++) {
  402. attr->pADsValues[i].dwType = ADSTYPE_DN_STRING;
  403. attr->pADsValues[i].DNString = pszAttr[i];
  404. }
  405. }
  406. void PackDWArrToAttrEx(ADS_ATTR_INFO *attr, WCHAR *szProperty, DWORD *pAttr, DWORD num,
  407. BOOL APPEND)
  408. {
  409. DWORD i;
  410. attr->pszAttrName = szProperty;
  411. attr->dwNumValues = num;
  412. if (APPEND)
  413. attr->dwControlCode = ADS_ATTR_APPEND;
  414. else
  415. attr->dwControlCode = ADS_ATTR_DELETE;
  416. attr->dwADsType = ADSTYPE_INTEGER;
  417. attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
  418. if (!(attr->pADsValues))
  419. return; // BUGBUG:: return the hresult.
  420. for (i = 0; i < num; i++) {
  421. attr->pADsValues[i].dwType = ADSTYPE_INTEGER;
  422. attr->pADsValues[i].Integer = pAttr[i];
  423. }
  424. }
  425. void PackGUIDArrToAttrEx(ADS_ATTR_INFO *attr, WCHAR *szProperty, GUID *pAttr, DWORD num,
  426. BOOL APPEND)
  427. {
  428. DWORD i;
  429. attr->pszAttrName = szProperty;
  430. attr->dwNumValues = num;
  431. if (APPEND)
  432. attr->dwControlCode = ADS_ATTR_APPEND;
  433. else
  434. attr->dwControlCode = ADS_ATTR_DELETE;
  435. attr->dwADsType = ADSTYPE_OCTET_STRING;
  436. attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
  437. if (!(attr->pADsValues))
  438. return; // BUGBUG:: return the hresult.
  439. for (i = 0; i < num; i++) {
  440. attr->pADsValues[i].dwType = ADSTYPE_OCTET_STRING;
  441. attr->pADsValues[i].OctetString.dwLength = sizeof(GUID);
  442. attr->pADsValues[i].OctetString.lpValue = (unsigned char *)(pAttr+i);
  443. }
  444. }
  445. void LogMessage(WCHAR *wszDebugBuffer)
  446. {
  447. HANDLE hFile = NULL;
  448. hFile = CreateFile(LOGFILE,
  449. GENERIC_WRITE,
  450. FILE_SHARE_READ,
  451. NULL,
  452. OPEN_ALWAYS,
  453. FILE_ATTRIBUTE_NORMAL,
  454. NULL);
  455. if ( hFile != INVALID_HANDLE_VALUE )
  456. {
  457. if ( SetFilePointer (hFile, 0, NULL, FILE_END) != 0xFFFFFFFF )
  458. {
  459. char * pszString;
  460. DWORD Size;
  461. int Status;
  462. Size = lstrlen(wszDebugBuffer) + 1;
  463. pszString = (char *) CoTaskMemAlloc( Size );
  464. if ( pszString )
  465. {
  466. Status = WideCharToMultiByte(
  467. CP_ACP,
  468. 0,
  469. wszDebugBuffer,
  470. -1,
  471. pszString,
  472. Size,
  473. NULL,
  474. NULL );
  475. if ( Status )
  476. {
  477. WriteFile(
  478. hFile,
  479. (LPCVOID) pszString,
  480. lstrlenA(pszString) * sizeof(char),
  481. &Size,
  482. NULL );
  483. }
  484. }
  485. CoTaskMemFree(pszString);
  486. }
  487. CloseHandle (hFile);
  488. }
  489. }
  490. void CSDbgPrint(WCHAR *Format, ...)
  491. {
  492. WCHAR wszDebugTitle[50], wszMsg[500];
  493. SYSTEMTIME systime;
  494. WCHAR wszDebugBuffer[500];
  495. DWORD dwErrCode = 0;
  496. va_list VAList;
  497. LPCTSTR Msg[1];
  498. if ((gDebugLog) || (gDebugOut))
  499. {
  500. dwErrCode = GetLastError();
  501. va_start(VAList, Format);
  502. GetLocalTime( &systime );
  503. wsprintf( wszDebugTitle, L"CSTORE (%x) %02d:%02d:%02d:%03d ",
  504. GetCurrentProcessId(),
  505. systime.wHour, systime.wMinute, systime.wSecond,
  506. systime.wMilliseconds);
  507. wvsprintf(wszMsg, Format, VAList);
  508. wsprintf(wszDebugBuffer, L"%s:: %s\n", wszDebugTitle, wszMsg);
  509. if (gDebugOut)
  510. OutputDebugString(wszDebugBuffer);
  511. if (gDebugLog)
  512. LogMessage(wszDebugBuffer);
  513. if (gDebugEventLog)
  514. {
  515. HANDLE hEventLogHandle;
  516. // we don't need time etc. for event log.
  517. // it should be added
  518. hEventLogHandle = RegisterEventSource(NULL, CLASSSTORE_EVENT_SOURCE);
  519. if (!hEventLogHandle)
  520. {
  521. #if DBG
  522. // Don't want to call call CSDBGPrint
  523. WCHAR Msg[_MAX_PATH];
  524. wsprintf(Msg, L"CSTORE: CSDbgPrint: Couldn't open event log. Error returned 0x%x\n", GetLastError());
  525. OutputDebugString(Msg);
  526. #endif // DBG
  527. }
  528. if (hEventLogHandle)
  529. {
  530. Msg[0] = wszMsg;
  531. ReportEvent(hEventLogHandle,
  532. EVENTLOG_INFORMATION_TYPE,
  533. 0,
  534. EVENT_CS_CLASSSTORE_DEBUGMSG,
  535. NULL,
  536. 1,
  537. 0,
  538. Msg,
  539. NULL
  540. );
  541. BOOL bDeregistered;
  542. bDeregistered = DeregisterEventSource(hEventLogHandle);
  543. if (!bDeregistered)
  544. {
  545. #if DBG
  546. // Don't want to call call CSDBGPrint
  547. WCHAR Msg[_MAX_PATH];
  548. wsprintf(Msg, L"CSTORE: CSDbgPrint: Couldn't Deregister event log. Error returned 0x%x\n", GetLastError());
  549. OutputDebugString(Msg);
  550. #endif // DBG
  551. }
  552. }
  553. }
  554. SetLastError(dwErrCode);
  555. }
  556. }