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.

1277 lines
30 KiB

  1. /*
  2. * IMEMX.C
  3. *
  4. * Per-instance global data for WINNT, WIN95 (trivial), WIN16, and Mac.
  5. *
  6. * Copyright 1993-1995 Microsoft Corporation. All Rights Reserved.
  7. */
  8. #pragma warning(disable:4100) /* unreferenced formal parameter */
  9. #pragma warning(disable:4201) /* nameless struct/union */
  10. #pragma warning(disable:4209) /* benign typedef redefinition */
  11. #pragma warning(disable:4214) /* bit field types other than int */
  12. #pragma warning(disable:4001) /* single line comments */
  13. #pragma warning(disable:4115) /* named type definition in parens */
  14. #ifdef WIN32
  15. #define INC_OLE2 /* Get the OLE2 stuff */
  16. #define INC_RPC /* harmless on Windows NT; Windows 95 needs it */
  17. #endif
  18. #include "_apipch.h"
  19. #ifdef DEBUG
  20. #define STATIC
  21. #else
  22. #define STATIC static
  23. #endif
  24. #pragma warning (disable:4514) /* unreferenced inline function */
  25. #ifdef WIN16
  26. #pragma code_seg("IMAlloc")
  27. #pragma warning(disable: 4005) /* redefines MAX_PATH */
  28. #undef MAX_PATH
  29. #include <toolhelp.h>
  30. #pragma warning(default: 4005)
  31. #pragma warning(disable: 4704) /* Inline assembler */
  32. BOOL
  33. FIsTask(HTASK hTask)
  34. {
  35. TASKENTRY teT;
  36. BOOL fSucceed = FALSE;
  37. teT.dwSize = sizeof(TASKENTRY);
  38. fSucceed = TaskFirst(&teT);
  39. while (fSucceed)
  40. {
  41. if (hTask == teT.hTask)
  42. break;
  43. fSucceed = TaskNext(&teT);
  44. }
  45. return fSucceed;
  46. }
  47. /*
  48. * The InstList structure holds three parallel arrays.
  49. * InstList.lprgwInstKey
  50. * Holds the stack segment of each task that calls
  51. * ScSetVerifyInstanceGlobals for the DLL we're in
  52. * Since all Win16 tasks share the same x86 segment descriptor tables,
  53. * no two tasks can have the same stack segment at the same time.
  54. * InstList.lprglpvInst
  55. * Holds a pointer to that task's instance globals in the slot with
  56. * the same index as the task SS in lprgwInstKey.
  57. * InstList.lprglpvInst
  58. * Holds a task indentifier that is guaranteed unique to the task through
  59. * the life (in memory) of the DLL. It is at the same index as the
  60. * task SS in lprgwInstKey.
  61. */
  62. /*
  63. - IFindInstEx
  64. -
  65. * Purpose:
  66. * Used to locate a particular task's instance pointer, and
  67. * also to find a free slot in the table.
  68. *
  69. * Arguments:
  70. * The value to look up. This is either a task's stack
  71. * segment, or 0 (if an empty slot is being sought).
  72. *
  73. * Returns:
  74. * Returns the index of the given value in rgwInstKey.
  75. * If the value is not present, returns cInstEntries.
  76. *
  77. */
  78. #pragma warning(disable: 4035) /* function return value done in asm */
  79. STATIC WORD
  80. IFindInstEx(WORD w, WORD FAR * lprgwInstKey, WORD cInstEntries)
  81. {
  82. #ifdef USE_C_EQUIVALENT
  83. WORD iInst, * pw = lprgwInstKey;
  84. for (iInst = 0; iInst < cInstEntries; ++pw, ++iInst)
  85. if (*pw == w)
  86. break;
  87. return(iInst);
  88. #else
  89. _asm
  90. {
  91. push es
  92. push di
  93. mov ax, w
  94. mov cx, cInstEntries
  95. mov bx, cx
  96. jcxz done
  97. les di, lprgwInstKey
  98. cld
  99. repne scasw
  100. jnz done
  101. sub bx, cx
  102. dec bx
  103. done: mov ax, bx
  104. pop di
  105. pop es
  106. };
  107. #endif
  108. }
  109. #pragma warning(default: 4035)
  110. /*
  111. - PvGetInstanceGlobalsEx
  112. -
  113. * Purpose:
  114. * Returns a pointer to the instance global data structre for
  115. * the current task.
  116. *
  117. * Returns:
  118. * Pointer to the instance data structure, or NULL if no
  119. * structure has yet been installed for this task.
  120. */
  121. LPVOID
  122. PvGetInstanceGlobalsInt(LPInstList lpInstList)
  123. {
  124. WORD iInst;
  125. WORD wMe;
  126. // get key for this process
  127. _asm
  128. {
  129. mov wMe,ss
  130. };
  131. /* First check cached value */
  132. if (lpInstList->wCachedKey == wMe)
  133. return lpInstList->lpvCachedInst;
  134. // Miss, do the lookup
  135. iInst = IFindInstEx( wMe
  136. , lpInstList->lprgwInstKey
  137. , lpInstList->cInstEntries);
  138. /* Cache and return the found value */
  139. if (iInst != lpInstList->cInstEntries)
  140. {
  141. lpInstList->wCachedKey = wMe;
  142. return (lpInstList->lpvCachedInst = lpInstList->lprglpvInst[iInst]);
  143. }
  144. /* If I get here then no instance was found
  145. */
  146. return NULL;
  147. }
  148. #if 0
  149. LPVOID
  150. PvGetVerifyInstanceGlobalsInt(DWORD dwPid, LPInstList lpInstList)
  151. {
  152. WORD iInst;
  153. WORD wMe;
  154. // get key for this process
  155. _asm
  156. {
  157. mov wMe,ss
  158. };
  159. // Always do the lookup
  160. iInst = IFindInstEx( wMe
  161. , lpInstList->lprgwInstKey
  162. , lpInstList->cInstEntries);
  163. /* If SS misses, return null right away */
  164. if (iInst == lpInstList->cInstEntries)
  165. return NULL;
  166. /* SS hit, now check the OLE process ID */
  167. if (dwPid != lpInstList->lprgdwPID[iInst])
  168. {
  169. /* Take no chances. Remove the entry and reset the cache. */
  170. lpInstList->wCachedKey = 0;
  171. lpInstList->lprgwInstKey[iInst] = 0;
  172. lpInstList->lprglpvInst[iInst] = 0;
  173. lpInstList->lprgdwPID[iInst] = 0;
  174. return NULL;
  175. }
  176. /* Cache and return the found value.
  177. */
  178. lpInstList->wCachedKey = wMe;
  179. lpInstList->lpvCachedInst = lpInstList->lprglpvInst[iInst];
  180. return lpInstList->lpvCachedInst;
  181. }
  182. #endif
  183. LPVOID
  184. PvSlowGetInstanceGlobalsInt(DWORD dwPid, LPInstList lpInstList)
  185. {
  186. WORD iInst;
  187. WORD cInstEntries = lpInstList->cInstEntries;
  188. /* Always do the lookup */
  189. for (iInst = 0; iInst < cInstEntries; ++iInst)
  190. {
  191. if (lpInstList->lprgdwPID[iInst] == dwPid)
  192. break;
  193. }
  194. /* If PID misses, return null */
  195. if (iInst == cInstEntries)
  196. return NULL;
  197. /* Return the found value. Do not cache; this function is being
  198. * called because SS is not what it "normally" is.
  199. */
  200. return lpInstList->lprglpvInst[iInst];
  201. }
  202. /*
  203. - ScSetVerifyInstanceGlobalsInt
  204. -
  205. * Purpose:
  206. * Installs or deinstalls instance global data for the current task.
  207. *
  208. * Arguments:
  209. * pv in Pointer to instance data structure (to
  210. * install); NULL (to deinstall).
  211. * dwPid in Zero or process ID, for better matching.
  212. *
  213. * Returns:
  214. * MAPI_E_NOT_ENOUGH_MEMORY if no slot is available in the
  215. * fixed-size table, else 0.
  216. */
  217. LONG
  218. ScSetVerifyInstanceGlobalsInt(LPVOID pv, DWORD dwPid, LPInstList lpInstList)
  219. {
  220. WORD iInst;
  221. WORD wMe;
  222. WORD cInstEntries = lpInstList->cInstEntries;
  223. // get key for this process
  224. _asm
  225. {
  226. mov wMe,ss
  227. };
  228. if (pv)
  229. {
  230. /* I am NOT supposed to be in the array at this time! */
  231. Assert( IFindInstEx(wMe, lpInstList->lprgwInstKey, cInstEntries)
  232. == cInstEntries);
  233. /* Installing instance globals. Find a free slot and park there. */
  234. Assert(cInstEntries || (lpInstList->dwInstFlags && INST_ALLOCATED));
  235. if (!cInstEntries)
  236. {
  237. DWORD cbMem = cInstChunk
  238. * (sizeof(WORD) + sizeof(LPVOID) + sizeof(DWORD)
  239. + sizeof(HTASK)); // raid 31090 lprghTask;
  240. if (!(lpInstList->lprgwInstKey
  241. = (WORD FAR *) GlobalAllocPtr( GPTR | GMEM_SHARE
  242. , cbMem)))
  243. {
  244. #ifdef DEBUG
  245. OutputDebugString("Instance list can't be allocated.\r\n");
  246. #endif
  247. return MAPI_E_NOT_ENOUGH_MEMORY;
  248. }
  249. ZeroMemory( lpInstList->lprgwInstKey, (size_t) cbMem);
  250. lpInstList->cInstEntries = cInstEntries = cInstChunk;
  251. lpInstList->lprglpvInst = (LPVOID FAR *) (lpInstList->lprgwInstKey + cInstEntries);
  252. lpInstList->lprgdwPID = (DWORD FAR *) (lpInstList->lprglpvInst + cInstEntries);
  253. lpInstList->lprghTask = (HTASK FAR *) (lpInstList->lprgdwPID + cInstEntries);
  254. }
  255. iInst = IFindInstEx(0, lpInstList->lprgwInstKey, cInstEntries);
  256. if (iInst == cInstEntries)
  257. {
  258. UINT uidx;
  259. // raid 31090: Time to do some scavanging. Find a HTASK that isn't
  260. // valid and use that slot.
  261. for ( uidx = 0; uidx < cInstEntries; uidx++ )
  262. {
  263. if ( !lpInstList->lprghTask[uidx] || !FIsTask( lpInstList->lprghTask[uidx] ) )
  264. {
  265. // found one
  266. iInst = uidx;
  267. break;
  268. }
  269. }
  270. if ( uidx == cInstEntries )
  271. {
  272. DebugTrace( "MAPI: ScSetVerifyInstanceGlobalsInt maxed out instance data and tasks can't be scavanged\n" );
  273. return MAPI_E_NOT_ENOUGH_MEMORY;
  274. }
  275. }
  276. // set the instance data
  277. lpInstList->lprglpvInst[iInst] = pv;
  278. lpInstList->lprgwInstKey[iInst] = wMe;
  279. lpInstList->lprgdwPID[iInst] = dwPid;
  280. lpInstList->lprghTask[iInst] = GetCurrentTask();
  281. /* Set the cache. */
  282. lpInstList->wCachedKey = wMe;
  283. lpInstList->lpvCachedInst = pv;
  284. }
  285. else
  286. {
  287. /* Deinstalling instance globals. Search and destroy. */
  288. iInst = IFindInstEx(wMe, lpInstList->lprgwInstKey, cInstEntries);
  289. if (iInst == cInstEntries)
  290. {
  291. #ifdef DEBUG
  292. OutputDebugString("No instance globals to reset\r\n");
  293. #endif
  294. return MAPI_E_NOT_INITIALIZED;
  295. }
  296. lpInstList->lprglpvInst[iInst] = NULL;
  297. lpInstList->lprgwInstKey[iInst] = 0;
  298. lpInstList->lprgdwPID[iInst] = 0L;
  299. /* Clear the cache. */
  300. lpInstList->wCachedKey = 0;
  301. lpInstList->lpvCachedInst = NULL;
  302. }
  303. return 0;
  304. }
  305. LONG
  306. ScSetInstanceGlobalsInt(LPVOID pv, LPInstList lpInstList)
  307. {
  308. return ScSetVerifyInstanceGlobalsInt(pv, 0L, lpInstList);
  309. }
  310. BOOL __export FAR PASCAL
  311. FCleanupInstanceGlobalsInt(LPInstList lpInstList)
  312. {
  313. /*
  314. * The docs say don't make Windows calls from this callback.
  315. * That means NO DEBUG TRACES
  316. */
  317. /* This code belongs in the WEP */
  318. /*
  319. * First, double-check that the DLL's data segment is available.
  320. * Code snitched from MSDN article "Loading, Initializing, and
  321. * Terminating a DLL."
  322. */
  323. /*
  324. _asm
  325. {
  326. push cx
  327. mov cx, ds ; get selector of interest
  328. lar ax, cx ; get selector access rights
  329. pop cx
  330. jnz bail ; failed, segment is bad
  331. test ax, 8000h ; if bit 8000 is clear, segment is not loaded
  332. jz bail ; we're OK
  333. };
  334. */
  335. //$DEBUG Assert non-zero entries here
  336. if ( (lpInstList->dwInstFlags & INST_ALLOCATED)
  337. && lpInstList->cInstEntries
  338. && lpInstList->lprgwInstKey)
  339. {
  340. GlobalFreePtr(lpInstList->lprgwInstKey);
  341. lpInstList->cInstEntries = lpInstList->wCachedKey
  342. = 0;
  343. lpInstList->lprgwInstKey = NULL;
  344. lpInstList->lprglpvInst = NULL;
  345. lpInstList->lprgdwPID = NULL;
  346. lpInstList->lpvCachedInst = NULL;
  347. }
  348. return 0; /* don't suppress further notifications */
  349. }
  350. #elif defined(MAC) /* !WIN16 */
  351. /*
  352. * The Mac implementation uses a linked list containing unique keys
  353. * to the calling process and pointers to instance data. This linked
  354. * list is n-dimensional because the Mac version often groups several
  355. * dlls into one exe.
  356. *
  357. * The OLE code that TomSax wrote allows us to keep track of the caller's
  358. * %a5 world when we call from another application. This code depends on
  359. * on that.
  360. *
  361. */
  362. typedef struct tag_INSTDATA {
  363. DWORD dwInstKey;
  364. DWORD dwPid;
  365. LPVOID lpvInst[kMaxSet];
  366. struct tag_INSTDATA *next;
  367. } INSTDATA, *LPINSTDATA, **HINSTDATA;
  368. LPINSTDATA lpInstHead = NULL;
  369. #define PvSlowGetInstanceGlobals(_dw, _dwId) PvGetVerifyInstanceGlobals(_dw, _dwId)
  370. VOID
  371. DisposeInstData(LPINSTDATA lpInstPrev, LPINSTDATA lpInst)
  372. {
  373. HINSTDATA hInstHead = &lpInstHead;
  374. /* This better only happen when both elements are NULL! */
  375. if (lpInst->lpvInst[kInstMAPIX] == lpInst->lpvInst[kInstMAPIU])
  376. {
  377. /* No inst data, remove element from linked list */
  378. if (lpInst == *hInstHead)
  379. *hInstHead = lpInst->next;
  380. else
  381. lpInstPrev->next = lpInst->next;
  382. DisposePtr((Ptr)lpInst);
  383. }
  384. }
  385. /*
  386. - PvGetInstanceGlobalsMac
  387. -
  388. * Purpose:
  389. * Returns a pointer to the instance global data structre for
  390. * the current task.
  391. *
  392. * Returns:
  393. * Pointer to the instance data structure, or NULL if no
  394. * structure has yet been installed for this task.
  395. */
  396. LPVOID FAR PASCAL
  397. PvGetInstanceGlobalsMac(WORD wDataSet)
  398. {
  399. HINSTDATA hInstHead = &lpInstHead;
  400. LPINSTDATA lpInst = *hInstHead;
  401. #ifdef DEBUG
  402. if (wDataSet >= kMaxSet)
  403. {
  404. DebugStr("\pPvGetInstanceGlobals : This data set has not been defined.");
  405. return NULL;
  406. }
  407. #endif
  408. while (lpInst)
  409. {
  410. if (lpInst->dwInstKey == (DWORD)LMGetCurrentA5())
  411. break;
  412. lpInst = lpInst->next;
  413. }
  414. if (lpInst == NULL)
  415. return NULL;
  416. return(lpInst->lpvInst[wDataSet]);
  417. }
  418. LPVOID FAR PASCAL
  419. PvGetVerifyInstanceGlobals(DWORD dwPid, DWORD wDataSet)
  420. {
  421. HINSTDATA hInstHead = &lpInstHead;
  422. LPINSTDATA lpInst, lpInstPrev;
  423. lpInst = lpInstPrev = *hInstHead;
  424. /* Always do the lookup */
  425. while (lpInst)
  426. {
  427. if (lpInst->dwInstKey == (DWORD)LMGetCurrentA5())
  428. break;
  429. lpInstPrev = lpInst;
  430. lpInst = lpInst->next;
  431. }
  432. /* If PvGetInstanceGlobals() misses, return NULL right away */
  433. if ((lpInst == NULL) || (lpInst->lpvInst[wDataSet] == NULL))
  434. return NULL;
  435. /* Found a match, now check the OLE process ID */
  436. if (dwPid != lpInst->dwPid)
  437. {
  438. DisposeInstData(lpInstPrev, lpInst);
  439. return NULL;
  440. }
  441. /* Return the found value */
  442. return lpInst->lpvInst[wDataSet];
  443. }
  444. /*
  445. - ScSetVerifyInstanceGlobals
  446. -
  447. * Purpose:
  448. * Installs or deinstalls instance global data for the current task.
  449. *
  450. * Arguments:
  451. * pv in Pointer to instance data structure (to
  452. * install); NULL (to deinstall).
  453. * dwPid in Zero or process ID, for better matching.
  454. * wDataSet in Inst data set to init or deinit (MAPIX or MAPIU)
  455. *
  456. * Returns:
  457. * MAPI_E_NOT_ENOUGH_MEMORY if a pointer of INSTDATA size cannot be
  458. * created, else 0.
  459. */
  460. LONG FAR PASCAL
  461. ScSetVerifyInstanceGlobals(LPVOID pv, DWORD dwPid, WORD wDataSet)
  462. {
  463. HINSTDATA hInstHead = &lpInstHead;
  464. LPINSTDATA lpInst, lpInstPrev;
  465. lpInst = lpInstPrev = *hInstHead;
  466. Assert(wDataSet < kMaxSet);
  467. /* Find our linked list element and the one before it */
  468. while (lpInst)
  469. {
  470. if (lpInst->dwInstKey == (DWORD)LMGetCurrentA5())
  471. break;
  472. lpInstPrev = lpInst;
  473. lpInst = lpInst->next;
  474. }
  475. if (pv)
  476. {
  477. if (lpInst)
  478. {
  479. /* I am NOT supposed to be in the array at this time! */
  480. Assert(lpInst->lpvInst[wDataSet] == NULL);
  481. lpInst->lpvInst[wDataSet] = pv;
  482. }
  483. else
  484. {
  485. /* Add a new linked list element and store <pv> there. */
  486. lpInst = (LPVOID) NewPtrClear(sizeof(INSTDATA));
  487. if (!lpInst)
  488. {
  489. #ifdef DEBUG
  490. OutputDebugString("Instance globals maxed out\r");
  491. #endif
  492. return MAPI_E_NOT_ENOUGH_MEMORY;
  493. }
  494. if (lpInstPrev)
  495. lpInstPrev->next = lpInst;
  496. else
  497. *hInstHead = lpInst;
  498. lpInst->dwInstKey = (DWORD)LMGetCurrentA5();
  499. lpInst->dwPid = dwPid;
  500. lpInst->lpvInst[wDataSet] = pv;
  501. }
  502. }
  503. else
  504. {
  505. /* Deinstalling instance globals. Search and destroy. */
  506. if (lpInst == NULL || lpInst->lpvInst[wDataSet] == NULL)
  507. {
  508. #ifdef DEBUG
  509. OutputDebugString("No instance globals to reset\r");
  510. #endif
  511. return MAPI_E_NOT_INITIALIZED;
  512. }
  513. /* The memory for <lpInst->lpvInst[wDataSet]> is disposed of */
  514. /* elsewhere. just as it was allocated elsewhere. */
  515. lpInst->lpvInst[wDataSet] = NULL;
  516. DisposeInstData(lpInstPrev, lpInst);
  517. }
  518. return 0;
  519. }
  520. LONG FAR PASCAL
  521. ScSetInstanceGlobalsMac(LPVOID pv, WORD wDataSet)
  522. {
  523. return ScSetVerifyInstanceGlobals(pv, 0L, wDataSet);
  524. }
  525. BOOL FAR PASCAL
  526. FCleanupInstanceGlobals(WORD wID, DWORD dwData)
  527. {
  528. /*
  529. * This is no longer used.
  530. *
  531. */
  532. #ifdef DEBUG
  533. DebugStr("\pCalled FCleanupInstanceGlobals : Empty function");
  534. #endif
  535. return 0;
  536. }
  537. #elif defined(_WINNT)
  538. /* NT implementation of instance list stuff goes here */
  539. // A new instance list is defined using "DefineInst(instance_name)"
  540. // A new instance list is declared using "DeclareInst(instance_name);"
  541. //
  542. // You then access them using the functions below (through macros
  543. // in _imemx.h)
  544. // Access to the instance lists must be serialized
  545. CRITICAL_SECTION csInstance;
  546. //
  547. // Each security context has its own instance. So that we can find
  548. // the right instance data for a particular security context at any
  549. // time, we maintain a global mapping of security contexts to instances
  550. // called the instance list. Entries in the instance list appear in no
  551. // particular order. That is, the list must always be searched linearly.
  552. // It is expected that the number of security contexts is sufficiently
  553. // small that a linear search is not a performance problem.
  554. //
  555. // Each entry in the instance list is just a struct which identifies a
  556. // security context and its associated instance.
  557. //
  558. typedef struct _MAPI_INSTANCE_DESCRIPTOR
  559. {
  560. ULARGE_INTEGER uliSecurity; // Security context identifier
  561. LPVOID lpInstance; // Pointer to associated instance data
  562. } MAPI_INSTANCE_DESCRIPTOR, *LPMAPI_INSTANCE_DESCRIPTOR;
  563. typedef struct _MAPI_INSTANCE_LIST
  564. {
  565. UINT cDescriptorsMax; // How many descriptors are in the array
  566. UINT cDescriptorsMac; // How many are currently in use
  567. MAPI_INSTANCE_DESCRIPTOR rgDescriptors[0];
  568. } MAPI_INSTANCE_LIST, *LPMAPI_INSTANCE_LIST;
  569. enum { INSTANCE_LIST_CHUNKSIZE = 20 };
  570. #define NEW_INSTANCE
  571. #if defined(NEW_INSTANCE)
  572. /*
  573. - UlCrcSid
  574. -
  575. * Purpose:
  576. * compute a CRC-32 based on a seed and value
  577. *
  578. * Ripped from runt.c because we don't want to introduce all of
  579. * that files dependencies just for one function
  580. *
  581. * Arguments:
  582. * cb size of data to hash
  583. * pb data to hash
  584. *
  585. * Returns:
  586. * new seed value
  587. *
  588. * Source:
  589. * UlCrc() in \mapi\src\common\runt.c
  590. */
  591. static ULONG
  592. UlCrcSid(UINT cb, LPBYTE pb)
  593. {
  594. int iLoop;
  595. int bit;
  596. DWORD dwSeed = 0;
  597. BYTE bValue;
  598. Assert(!IsBadReadPtr(pb, cb));
  599. while (cb--)
  600. {
  601. bValue = *pb++;
  602. dwSeed ^= bValue;
  603. for (iLoop = 0; iLoop < 8; iLoop++)
  604. {
  605. bit = (int)(dwSeed & 0x1);
  606. dwSeed >>= 1;
  607. if (bit)
  608. dwSeed ^= 0xedb88320;
  609. }
  610. }
  611. return dwSeed;
  612. }
  613. /*++
  614. Routine Description:
  615. Returns the size and CRC of the SID that this code is running in the
  616. account of. Should make a pretty good 64-bit number to uniqify by.
  617. Arguments:
  618. None
  619. Return Value:
  620. BOOL - if everything worked. Call the systems GetLastError() if
  621. it didn't.
  622. *lpulSize - size of the SID
  623. *lpulCRC - CRC-32 of the SID
  624. !!! This function is duplicated in \mapi\src\glh\glglobal.c
  625. !!! We really need to put it in a static LIB!
  626. --*/
  627. static
  628. BOOL WINAPI GetAccountCRC( ULONG *lpulSize, ULONG *lpulCRC)
  629. {
  630. BOOL fHappen = FALSE; // Assume the function failed
  631. HANDLE hTok = NULL;
  632. // max size of sid + TOKEN_USER base
  633. #define TOKENBUFFSIZE (256*6) + sizeof (TOKEN_USER)
  634. BYTE tokenbuff[TOKENBUFFSIZE];
  635. ULONG ulcbTok = TOKENBUFFSIZE;
  636. TOKEN_USER *ptu = (TOKEN_USER *) tokenbuff;
  637. // Open the process and the process token, and get out the
  638. // security ID.
  639. if (!OpenThreadToken(GetCurrentThread(),
  640. TOKEN_QUERY, TRUE, //$ TRUE for Process security!
  641. &hTok))
  642. {
  643. if (!OpenThreadToken(GetCurrentThread(),
  644. TOKEN_QUERY, FALSE, // Sometimes process security doesn't work!
  645. &hTok))
  646. {
  647. if (!OpenProcessToken(GetCurrentProcess(),
  648. TOKEN_QUERY,
  649. &hTok))
  650. goto out;
  651. }
  652. }
  653. fHappen = GetTokenInformation(hTok,
  654. TokenUser,
  655. ptu,
  656. ulcbTok,
  657. &ulcbTok);
  658. #ifdef DEBUG
  659. AssertSz1 (fHappen, "GetTokenInformation fails with error %lu", GetLastError());
  660. if ( fHappen &&
  661. GetPrivateProfileInt("General", "TraceInstContext", 0, "mapidbg.ini") )
  662. {
  663. DWORD dwAccount;
  664. CHAR rgchAccount[MAX_PATH+1];
  665. DWORD dwDomain;
  666. CHAR rgchDomain[MAX_PATH+1];
  667. SID_NAME_USE snu;
  668. dwAccount = sizeof(rgchAccount);
  669. dwDomain = sizeof(rgchDomain);
  670. if ( LookupAccountSid( NULL,
  671. ptu->User.Sid,
  672. rgchAccount,
  673. &dwAccount,
  674. rgchDomain,
  675. &dwDomain,
  676. &snu ) )
  677. {
  678. DebugTrace( "Locating MAPI instance for %s:%s\n", rgchDomain, rgchAccount );
  679. }
  680. }
  681. #endif
  682. //
  683. // We should have the TOKEN_USER data now. Get the size of the
  684. // contained SID then calculate its CRC.
  685. //
  686. if (fHappen && ulcbTok != 0 && (ptu->User.Sid != NULL))
  687. {
  688. *lpulSize = GetLengthSid (ptu->User.Sid);
  689. *lpulCRC = UlCrcSid(*lpulSize, (LPBYTE) ptu->User.Sid);
  690. }
  691. #ifdef DEBUG
  692. else
  693. AssertSz (FALSE, "GetAccountCRC failed to get the SID");
  694. #endif
  695. out:
  696. if (hTok)
  697. CloseHandle(hTok);
  698. return fHappen;
  699. }
  700. /*
  701. - ForeachInstance() [EXTERNAL]
  702. -
  703. * Purpose:
  704. * Iterates over all instances in an instance list
  705. * performing the specified action on each
  706. *
  707. * Arguments:
  708. * pfnAction Action to do for each instance. Must be
  709. * a void function taking a pointer to
  710. * instance data as a parameter.
  711. * lpInstList Instance list
  712. *
  713. * Returns:
  714. * nothing
  715. */
  716. VOID FAR PASCAL
  717. ForeachInstance( INSTACTION * pfnAction,
  718. LPVOID pvInstList )
  719. {
  720. UINT iDescriptor;
  721. //
  722. // If there's no descriptor list, then there are obviously
  723. // no descriptors and hence no instances to which an
  724. // action can be applied.
  725. //
  726. if ( pvInstList == NULL )
  727. goto ret;
  728. //
  729. // Trundle down the descriptor list applying the
  730. // specified action to each instance therein.
  731. //
  732. for ( iDescriptor = 0;
  733. iDescriptor < ((LPMAPI_INSTANCE_LIST) pvInstList)->cDescriptorsMac;
  734. iDescriptor++ )
  735. {
  736. pfnAction( ((LPMAPI_INSTANCE_LIST) pvInstList)->rgDescriptors[iDescriptor].lpInstance );
  737. }
  738. ret:
  739. return;
  740. }
  741. /*
  742. - LpFindInstanceDescriptor()
  743. -
  744. * Purpose:
  745. * Looks in the instance descriptor list for an instance
  746. * descriptor corresponding to the specified security
  747. * context.
  748. *
  749. * Arguments:
  750. * lpInstList Instance list
  751. * uliSecurity CRC'd security context
  752. *
  753. * Returns:
  754. * A pointer to the instance descriptor or NULL if there is
  755. * no instance descriptor for the specified security context.
  756. */
  757. LPMAPI_INSTANCE_DESCRIPTOR
  758. LpFindInstanceDescriptor( LPMAPI_INSTANCE_LIST lpInstList,
  759. ULARGE_INTEGER uliSecurity )
  760. {
  761. LPMAPI_INSTANCE_DESCRIPTOR lpDescriptorFound = NULL;
  762. UINT iDescriptor;
  763. //
  764. // If there's no descriptor list, then there are obviously
  765. // no descriptors matching this security context.
  766. //
  767. if ( lpInstList == NULL )
  768. goto ret;
  769. //
  770. // Trundle down the descriptor list looking for our context.
  771. // If we find it, then return its associated descriptor.
  772. //
  773. for ( iDescriptor = 0;
  774. iDescriptor < lpInstList->cDescriptorsMac;
  775. iDescriptor++ )
  776. {
  777. if ( lpInstList->rgDescriptors[iDescriptor].uliSecurity.QuadPart ==
  778. uliSecurity.QuadPart )
  779. {
  780. lpDescriptorFound = &lpInstList->rgDescriptors[iDescriptor];
  781. break;
  782. }
  783. }
  784. ret:
  785. return lpDescriptorFound;
  786. }
  787. /*
  788. - ScNewInstanceDescriptor()
  789. -
  790. * Purpose:
  791. * Creates a new instance descriptor in the instance descriptor list,
  792. * allocating or growing the list as necessary.
  793. *
  794. * Arguments:
  795. * plpInstList Pointer to instance list
  796. * uliSecurity CRC'd security context
  797. * pvInstance Associated instance
  798. * plpDescriptorNew Pointer to returned descriptor
  799. *
  800. * Returns:
  801. * A pointer to a new 0-filled instance descriptor added to
  802. * to the instance descriptor list.
  803. */
  804. __inline UINT
  805. CbNewInstanceList( UINT cDescriptors )
  806. {
  807. return offsetof(MAPI_INSTANCE_LIST, rgDescriptors) +
  808. sizeof(MAPI_INSTANCE_DESCRIPTOR) * cDescriptors;
  809. }
  810. SCODE
  811. ScNewInstanceDescriptor( LPMAPI_INSTANCE_LIST * plpInstList,
  812. ULARGE_INTEGER uliSecurity,
  813. LPVOID pvInstance,
  814. LPMAPI_INSTANCE_DESCRIPTOR * plpDescriptorNew )
  815. {
  816. LPMAPI_INSTANCE_DESCRIPTOR lpDescriptor = NULL;
  817. SCODE sc = S_OK;
  818. Assert( !IsBadWritePtr( plpInstList, sizeof(LPMAPI_INSTANCE_LIST) ) );
  819. Assert( !IsBadWritePtr( plpDescriptorNew, sizeof(LPMAPI_INSTANCE_DESCRIPTOR) ) );
  820. //
  821. // Allocate/Grow the descriptor list if necessary.
  822. //
  823. if ( *plpInstList == NULL ||
  824. (*plpInstList)->cDescriptorsMac == (*plpInstList)->cDescriptorsMax )
  825. {
  826. LPMAPI_INSTANCE_LIST lpInstListNew;
  827. lpInstListNew = (*plpInstList == NULL) ?
  828. HeapAlloc( GetProcessHeap(),
  829. HEAP_ZERO_MEMORY,
  830. CbNewInstanceList( INSTANCE_LIST_CHUNKSIZE ) ) :
  831. HeapReAlloc( GetProcessHeap(),
  832. HEAP_ZERO_MEMORY,
  833. *plpInstList,
  834. CbNewInstanceList( INSTANCE_LIST_CHUNKSIZE +
  835. (*plpInstList)->cDescriptorsMax ) );
  836. if ( lpInstListNew == NULL )
  837. {
  838. DebugTrace( "ScNewInstanceDescriptor() - Error allocating/growing descriptor list (%d)\n", GetLastError() );
  839. sc = MAPI_E_NOT_ENOUGH_MEMORY;
  840. goto ret;
  841. }
  842. *plpInstList = lpInstListNew;
  843. (*plpInstList)->cDescriptorsMax += INSTANCE_LIST_CHUNKSIZE;
  844. }
  845. //
  846. // Grab the next available descriptor
  847. //
  848. *plpDescriptorNew = &(*plpInstList)->rgDescriptors[
  849. (*plpInstList)->cDescriptorsMac];
  850. ++(*plpInstList)->cDescriptorsMac;
  851. //
  852. // Fill in its security context and instance
  853. //
  854. (*plpDescriptorNew)->uliSecurity = uliSecurity;
  855. (*plpDescriptorNew)->lpInstance = pvInstance;
  856. ret:
  857. return sc;
  858. }
  859. /*
  860. - DeleteInstanceDescriptor()
  861. -
  862. * Purpose:
  863. * Removes the specified instance descriptor from the instance
  864. * descriptor list. Frees and re-NULLs the list when the last
  865. * descriptor is removed.
  866. *
  867. * Arguments:
  868. * plpInstList Pointer to instance descriptor list
  869. * lpDescriptor Descriptor to remove
  870. *
  871. * Returns:
  872. * Nothing.
  873. */
  874. VOID
  875. DeleteInstanceDescriptor( LPMAPI_INSTANCE_LIST * plpInstList,
  876. LPMAPI_INSTANCE_DESCRIPTOR lpDescriptor )
  877. {
  878. Assert( !IsBadWritePtr(plpInstList, sizeof(LPMAPI_INSTANCE_LIST)) );
  879. Assert( *plpInstList != NULL );
  880. Assert( lpDescriptor >= (*plpInstList)->rgDescriptors );
  881. Assert( lpDescriptor < (*plpInstList)->rgDescriptors + (*plpInstList)->cDescriptorsMac );
  882. Assert( ((LPBYTE)lpDescriptor - (LPBYTE)(*plpInstList)->rgDescriptors) %
  883. sizeof(MAPI_INSTANCE_DESCRIPTOR) == 0 );
  884. MoveMemory( lpDescriptor,
  885. lpDescriptor + 1,
  886. sizeof(MAPI_INSTANCE_DESCRIPTOR) *
  887. ((*plpInstList)->cDescriptorsMac -
  888. ((lpDescriptor - (*plpInstList)->rgDescriptors) + 1) ) );
  889. --(*plpInstList)->cDescriptorsMac;
  890. if ( (*plpInstList)->cDescriptorsMac == 0 )
  891. {
  892. HeapFree( GetProcessHeap(), 0, *plpInstList );
  893. *plpInstList = NULL;
  894. }
  895. }
  896. /*
  897. - PvGetInstanceGlobalsExInt() [EXTERNAL]
  898. -
  899. * Purpose:
  900. * Fetch the instance globals for the current security context.
  901. *
  902. * Arguments:
  903. * ppvInstList Transparent pointer to instance descriptor list
  904. *
  905. * Returns:
  906. * Pointer to the instance globals.
  907. */
  908. LPVOID FAR PASCAL
  909. PvGetInstanceGlobalsExInt (LPVOID * ppvInstList)
  910. {
  911. LPMAPI_INSTANCE_DESCRIPTOR lpDescriptor;
  912. ULARGE_INTEGER uliSecurity;
  913. LPVOID lpvInstanceRet = NULL;
  914. EnterCriticalSection (&csInstance);
  915. //
  916. // Get our security context.
  917. //
  918. SideAssertSz1(
  919. GetAccountCRC (&uliSecurity.LowPart, &uliSecurity.HighPart) != 0,
  920. "PvGetInstanceGlobalsExInt: Failed to get account info (%d)",
  921. GetLastError() );
  922. //
  923. // Look for a descriptor in the descriptor list
  924. // with our security context.
  925. //
  926. lpDescriptor = LpFindInstanceDescriptor( *ppvInstList, uliSecurity );
  927. //
  928. // If we find one, then return its associated instance.
  929. // Return NULL if we didn't find one.
  930. //
  931. if ( lpDescriptor != NULL )
  932. lpvInstanceRet = lpDescriptor->lpInstance;
  933. LeaveCriticalSection (&csInstance);
  934. return lpvInstanceRet;
  935. }
  936. /*
  937. - ScSetInstanceGlobalsExInt() [EXTERNAL]
  938. -
  939. * Purpose:
  940. * Assigns (new) instance globals for the current security context.
  941. *
  942. * Arguments:
  943. * pvInstNew Instance globals
  944. * ppvInstList Transparent pointer to instance descriptor list
  945. *
  946. * Returns:
  947. * Success or failure SCODE.
  948. */
  949. SCODE FAR PASCAL
  950. ScSetInstanceGlobalsExInt (LPVOID pvInstNew, LPVOID *ppvInstList)
  951. {
  952. LPMAPI_INSTANCE_DESCRIPTOR lpDescriptor;
  953. ULARGE_INTEGER uliSecurity;
  954. SCODE sc = S_OK;
  955. EnterCriticalSection (&csInstance);
  956. //
  957. // Get our security context.
  958. //
  959. SideAssertSz1(
  960. GetAccountCRC (&uliSecurity.LowPart, &uliSecurity.HighPart) != 0,
  961. "ScSetInstanceGlobalsExInt: Failed to get account info (%d)",
  962. GetLastError() );
  963. //
  964. // Look for a descriptor in the descriptor list
  965. // with our security context.
  966. //
  967. lpDescriptor = LpFindInstanceDescriptor( *ppvInstList, uliSecurity );
  968. //
  969. // If we find one then replace its instance
  970. //
  971. if ( lpDescriptor != NULL )
  972. {
  973. lpDescriptor->lpInstance = pvInstNew;
  974. }
  975. //
  976. // If we don't find a descriptor then create a new one
  977. // for this security context and instance
  978. //
  979. else
  980. {
  981. sc = ScNewInstanceDescriptor( (LPMAPI_INSTANCE_LIST *) ppvInstList,
  982. uliSecurity,
  983. pvInstNew,
  984. &lpDescriptor );
  985. if ( sc != S_OK )
  986. {
  987. DebugTrace( "Error creating new instance descriptor (%s)\n", SzDecodeScode(sc) );
  988. goto ret;
  989. }
  990. }
  991. ret:
  992. LeaveCriticalSection (&csInstance);
  993. return sc;
  994. }
  995. /*
  996. - ScDeleteInstanceGlobalsExInt() [EXTERNAL]
  997. -
  998. * Purpose:
  999. * Uninstalls instance globals for the current security context.
  1000. *
  1001. * Arguments:
  1002. * ppvInstList Transparent pointer to instance descriptor list
  1003. *
  1004. * Returns:
  1005. * S_OK
  1006. */
  1007. SCODE FAR PASCAL
  1008. ScDeleteInstanceGlobalsExInt (LPVOID *ppvInstList)
  1009. {
  1010. LPMAPI_INSTANCE_DESCRIPTOR lpDescriptor;
  1011. ULARGE_INTEGER uliSecurity;
  1012. EnterCriticalSection (&csInstance);
  1013. //
  1014. // Get our security context.
  1015. //
  1016. SideAssertSz1(
  1017. GetAccountCRC (&uliSecurity.LowPart, &uliSecurity.HighPart) != 0,
  1018. "ScDeleteInstanceGlobalsExInt: Failed to get account info (%d)",
  1019. GetLastError() );
  1020. //
  1021. // Look for a descriptor in the descriptor list
  1022. // with our security context.
  1023. //
  1024. lpDescriptor = LpFindInstanceDescriptor( *ppvInstList, uliSecurity );
  1025. //
  1026. // If we find one, then remove it from the list. Don't worry if we
  1027. // don't find one. We may be cleaning up after a failed initialization.
  1028. //
  1029. if ( lpDescriptor != NULL )
  1030. DeleteInstanceDescriptor( (LPMAPI_INSTANCE_LIST *) ppvInstList,
  1031. lpDescriptor );
  1032. LeaveCriticalSection (&csInstance);
  1033. return S_OK;
  1034. }
  1035. #else // !defined(NEW_INSTANCE)
  1036. SCODE FAR PASCAL
  1037. ScSetInstanceGlobalsExInt (LPVOID pvInstNew, LPVOID *ppvInstList)
  1038. {
  1039. *ppvInstList = pvInstNew;
  1040. return S_OK;
  1041. }
  1042. LPVOID FAR PASCAL
  1043. PvGetInstanceGlobalsExInt (LPVOID *ppvInstList)
  1044. {
  1045. lpvReturn = *ppvInstList;
  1046. }
  1047. SCODE FAR PASCAL
  1048. ScDeleteInstanceGlobalsExInt (LPVOID *ppvInstList)
  1049. {
  1050. *ppvInstList = NULL;
  1051. return S_OK;
  1052. }
  1053. #endif // !defined(NEW_INSTANCE)
  1054. #elif defined(_WIN95)
  1055. /* There is nothing to do here for Win95.
  1056. * Using "DefineInst(pinstX)" to define your instance pointer
  1057. * and "DeclareInst(pinstX)" to declare external refs is enough.
  1058. */
  1059. #endif