IMEM.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:15k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * IMEM.C
- *
- * Per-instance global data for WIN32 (trivial), WIN16, and Mac.
- *
- * Copyright 1993-1995 Microsoft Corporation. All Rights Reserved.
- */
- #pragma warning(disable:4100) /* unreferenced formal parameter */
- #pragma warning(disable:4201) /* nameless struct/union */
- #pragma warning(disable:4209) /* benign typedef redefinition */
- #pragma warning(disable:4214) /* bit field types other than int */
- #pragma warning(disable:4001) /* single line comments */
- #pragma warning(disable:4115) /* named type definition in parens */
- #ifdef _WIN32
- #define INC_OLE2 /* Get the OLE2 stuff */
- #define INC_RPC /* harmless on Windows NT; Windows 95 needs it */
- #endif
- #include <windows.h>
- #include <windowsx.h>
- #include <mapiwin.h>
- #if defined (_WIN32) && !defined (_MAC)
- #pragma warning(disable:4001) /* single line comments */
- #include <objerror.h>
- #include <objbase.h>
- #endif
- #ifdef WIN16
- #include <compobj.h>
- #endif
- #include <mapicode.h>
- #include <mapidbg.h>
- #ifdef _MAC
- #include <macname1.h>
- #include <macoslowmem.h>
- #include <macname2.h>
- #include <utilmac.h>
- #endif
- #ifdef DEBUG
- #define STATIC
- #else
- #define STATIC static
- #endif
- #pragma warning (disable:4514) /* unreferenced inline function */
- #ifdef WIN16
- #pragma code_seg("IMAlloc")
- #pragma warning(disable: 4005) /* redefines MAX_PATH */
- #include <toolhelp.h>
- #pragma warning(default: 4005)
- #pragma warning(disable: 4704) /* Inline assembler */
- /*
- * These arrays are parallel. RgwInstKey holds the stack
- * segment of each task that calls the DLL we're in; rgpvInst
- * has a pointer to that task's instance globals in the slot with
- * the same index. Since all Win16 tasks share the same x86
- * segment descriptor tables, no two tasks can have the same stack
- * segment.
- *
- * Note carefully the last elements of the initializers. The value
- * in rgwInstKey is a sentinel, which will always stop the scan
- * whether the value being sought is a valid stack segment or
- * zero.
- */
- STATIC WORD rgwInstKey[cInstMax+1]= { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xFFFF };
- STATIC LPVOID rgpvInst[cInstMax+1]= { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
- STATIC DWORD rgdwPid[cInstMax+1]= { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
- STATIC WORD wCachedKey = 0;
- STATIC LPVOID pvCachedInst = NULL;
- /*
- - IFindInst
- -
- * Purpose:
- * Used to locate a particular task's instance pointer, and
- * also to find a free slot in the table.
- *
- * Arguments:
- * The value to look up. This is either a task's stack
- * segment, or 0 (if an empty slot is being sought).
- *
- * Returns:
- * Returns the index of the given value in rgwInstKey.
- * If the value is not present, returns cInstMax.
- *
- */
- #pragma warning(disable: 4035) /* function return value done in asm */
- STATIC int
- IFindInst(WORD w)
- {
- _asm
- {
- mov cx,cInstMax+1 /* count includes sentinel */
- mov ax,ds /* point es:di at rgwInstKey */
- mov es,ax
- mov di,OFFSET rgwInstKey
- mov ax,w /* scan for this value */
- cld /* scan forward... */
- repne scasw /* go */
- mov ax,cx /* Convert the number of items remaining */
- sub ax,cInstMax+1 /* to the index of the item found. */
- inc ax
- neg ax
- }
- }
- #pragma warning(default: 4035)
- /*
- - PvGetInstanceGlobals
- -
- * Purpose:
- * Returns a pointer to the instance global data structre for
- * the current task.
- *
- * Returns:
- * Pointer to the instance data structure, or NULL if no
- * structure has yet been installed for this task.
- */
- LPVOID FAR PASCAL
- PvGetInstanceGlobals(void)
- {
- int iInst;
- WORD wMe;
- _asm mov wMe,ss ; get key for this process
- /* First check cached value */
- if (wCachedKey == wMe)
- return pvCachedInst;
- /* Miss, do the lookup */
- iInst = IFindInst(wMe);
- /* Cache and return the found value */
- if (iInst != cInstMax)
- {
- wCachedKey = wMe;
- pvCachedInst = rgpvInst[iInst];
- }
- return rgpvInst[iInst]; /* Note: parallel to the lookup sentinel */
- }
- LPVOID FAR PASCAL
- PvGetVerifyInstanceGlobals(DWORD dwPid)
- {
- int iInst;
- WORD wMe;
- _asm mov wMe,ss ; get key for this process
- /* Always do the lookup */
- iInst = IFindInst(wMe);
- /* If SS misses, return null right away */
- if (iInst == cInstMax)
- return NULL;
- /* SS hit, now check the OLE process ID */
- if (dwPid != rgdwPid[iInst])
- {
- wCachedKey = 0; /* Take no chances */
- rgwInstKey[iInst] = 0;
- rgpvInst[iInst] = 0;
- rgdwPid[iInst] = 0;
- return NULL;
- }
- /* Cache and return the found value */
- wCachedKey = wMe;
- pvCachedInst = rgpvInst[iInst];
- return pvCachedInst;
- }
- LPVOID FAR PASCAL
- PvSlowGetInstanceGlobals(DWORD dwPid)
- {
- int iInst;
- /* Always do the lookup */
- for (iInst = 0; iInst < cInstMax; ++iInst)
- {
- if (rgdwPid[iInst] == dwPid)
- break;
- }
- /* If PID misses, return null */
- if (iInst == cInstMax)
- return NULL;
- /* Return the found value. Do not cache; this function is being
- * called because SS is not what it "normally" is.
- */
- return rgpvInst[iInst];
- }
- /*
- - ScSetVerifyInstanceGlobals
- -
- * Purpose:
- * Installs or deinstalls instance global data for the current task.
- *
- * Arguments:
- * pv in Pointer to instance data structure (to
- * install); NULL (to deinstall).
- * dwPid in Zero or process ID, for better matching.
- *
- * Returns:
- * MAPI_E_NOT_ENOUGH_MEMORY if no slot is available in the
- * fixed-size table, else 0.
- */
- LONG FAR PASCAL
- ScSetVerifyInstanceGlobals(LPVOID pv, DWORD dwPid)
- {
- int iInst;
- WORD wMe;
- _asm mov wMe,ss
- if (pv)
- {
- /* I am NOT supposed to be in the array at this time! */
- Assert(IFindInst(wMe) == cInstMax);
- /* Installing instance globals. Find a free slot and park there. */
- iInst = IFindInst(0);
- if (iInst == cInstMax)
- {
- #ifdef DEBUG
- OutputDebugString("Instance globals maxed outrn");
- #endif
- return MAPI_E_NOT_ENOUGH_MEMORY;
- }
- rgpvInst[iInst] = pv;
- rgwInstKey[iInst] = wMe;
- rgdwPid[iInst] = dwPid;
- /* Set the cache. */
- wCachedKey = wMe;
- pvCachedInst = pv;
- }
- else
- {
- /* Deinstalling instance globals. Search and destroy. */
- iInst = IFindInst(wMe);
- if (iInst == cInstMax)
- {
- #ifdef DEBUG
- OutputDebugString("No instance globals to resetrn");
- #endif
- return MAPI_E_NOT_INITIALIZED;
- }
- rgpvInst[iInst] = NULL;
- rgwInstKey[iInst] = 0;
- rgdwPid[iInst] = 0L;
- /* Clear the cache. */
- wCachedKey = 0;
- pvCachedInst = NULL;
- }
- return 0;
- }
- LONG FAR PASCAL
- ScSetInstanceGlobals(LPVOID pv)
- {
- return ScSetVerifyInstanceGlobals(pv, 0L);
- }
- BOOL __export FAR PASCAL
- FCleanupInstanceGlobals(WORD wID, DWORD dwData)
- {
- int iInst;
- WORD wMe;
- /*
- * Would be nice if we could release the pmalloc
- * and the inst structure in this function, but docs say
- * don't make Windows calls from this callback.
- * That means also NO DEBUG TRACES
- */
- /*
- * First, double-check that the DLL's data segment is available.
- * Code snitched from MSDN article "Loading, Initializing, and
- * Terminating a DLL."
- */
- _asm
- {
- push cx
- mov cx, ds ; get selector of interest
- lar ax, cx ; get selector access rights
- pop cx
- jnz bail ; failed, segment is bad
- test ax, 8000h ; if bit 8000 is clear, segment is not loaded
- jz bail ; we're OK
- }
- if (wID == NFY_EXITTASK)
- {
- _asm mov wMe,ss
- iInst = IFindInst(wMe);
- if (iInst < cInstMax)
- {
- /* Clear this process's entry */
- rgpvInst[iInst] = NULL;
- rgwInstKey[iInst] = 0;
- }
- /* Clear the cache too */
- wCachedKey = 0;
- pvCachedInst = NULL;
- }
- bail:
- return 0; /* don't suppress further notifications */
- }
- #elif defined(_MAC) /* !WIN16 */
- #pragma code_seg("imalloc", "fixed")
- /*
- * The Mac implementation uses a linked list containing unique keys
- * to the calling process and pointers to instance data. This linked
- * list is n-dimensional because the Mac version often groups several
- * dlls into one exe.
- *
- * The OLE code that TomSax wrote allows us to keep track of the caller's
- * %a5 world when we call from another application. This code depends on
- * on that.
- *
- */
- typedef struct tag_INSTDATA {
- DWORD dwInstKey;
- DWORD dwPid;
- LPVOID lpvInst[kMaxSet];
- struct tag_INSTDATA *next;
- } INSTDATA, *LPINSTDATA, **HINSTDATA;
- LPINSTDATA lpInstHead = NULL;
- #define PvSlowGetInstanceGlobals(_dw, _dwId) PvGetVerifyInstanceGlobals(_dw, _dwId)
- VOID
- DisposeInstData(LPINSTDATA lpInstPrev, LPINSTDATA lpInst)
- {
- HINSTDATA hInstHead = &lpInstHead;
- /* This better only happen when both elements are NULL! */
- if (lpInst->lpvInst[kInstMAPIX] == lpInst->lpvInst[kInstMAPIU])
- {
- /* No inst data, remove element from linked list */
- if (lpInst == *hInstHead)
- *hInstHead = lpInst->next;
- else
- lpInstPrev->next = lpInst->next;
- DisposePtr((Ptr)lpInst);
- }
- }
- /*
- - PvGetInstanceGlobals
- -
- * Purpose:
- * Returns a pointer to the instance global data structre for
- * the current task.
- *
- * Returns:
- * Pointer to the instance data structure, or NULL if no
- * structure has yet been installed for this task.
- */
- LPVOID FAR PASCAL
- PvGetInstanceGlobals(WORD wDataSet)
- {
- HINSTDATA hInstHead = &lpInstHead;
- LPINSTDATA lpInst = *hInstHead;
- #ifdef DEBUG
- if (wDataSet >= kMaxSet)
- {
- DebugStr("pPvGetInstanceGlobals : This data set has not been defined.");
- return NULL;
- }
- #endif
- while (lpInst)
- {
- if (lpInst->dwInstKey == (DWORD)LMGetCurrentA5())
- break;
- lpInst = lpInst->next;
- }
- return(lpInst->lpvInst[wDataSet]);
- }
- LPVOID FAR PASCAL
- PvGetVerifyInstanceGlobals(DWORD dwPid, DWORD wDataSet)
- {
- HINSTDATA hInstHead = &lpInstHead;
- LPINSTDATA lpInst, lpInstPrev;
- lpInst = lpInstPrev = *hInstHead;
- /* Always do the lookup */
- while (lpInst)
- {
- if (lpInst->dwInstKey == (DWORD)LMGetCurrentA5())
- break;
- lpInstPrev = lpInst;
- lpInst = lpInst->next;
- }
- /* If PvGetInstanceGlobals() misses, return NULL right away */
- if (lpInst->lpvInst[wDataSet] == NULL)
- return NULL;
- /* Found a match, now check the OLE process ID */
- if (dwPid != lpInst->dwPid)
- {
- DisposeInstData(lpInstPrev, lpInst);
- return NULL;
- }
- /* Return the found value */
- return lpInst->lpvInst[wDataSet];
- }
- /*
- - ScSetVerifyInstanceGlobals
- -
- * Purpose:
- * Installs or deinstalls instance global data for the current task.
- *
- * Arguments:
- * pv in Pointer to instance data structure (to
- * install); NULL (to deinstall).
- * dwPid in Zero or process ID, for better matching.
- * wDataSet in Inst data set to init or deinit (MAPIX or MAPIU)
- *
- * Returns:
- * MAPI_E_NOT_ENOUGH_MEMORY if a pointer of INSTDATA size cannot be
- * created, else 0.
- */
- LONG FAR PASCAL
- ScSetVerifyInstanceGlobals(LPVOID pv, DWORD dwPid, WORD wDataSet)
- {
- HINSTDATA hInstHead = &lpInstHead;
- LPINSTDATA lpInst, lpInstPrev;
- lpInst = lpInstPrev = *hInstHead;
- Assert(wDataSet < kMaxSet);
- /* Find our linked list element and the one before it */
- while (lpInst)
- {
- if (lpInst->dwInstKey == (DWORD)LMGetCurrentA5())
- break;
- lpInstPrev = lpInst;
- lpInst = lpInst->next;
- }
- if (pv)
- {
- if (lpInst)
- {
- /* I am NOT supposed to be in the array at this time! */
- Assert(lpInst->lpvInst[wDataSet] == NULL);
- lpInst->lpvInst[wDataSet] = pv;
- }
- else
- {
- /* Add a new linked list element and store <pv> there. */
- lpInst = (LPVOID) NewPtrClear(sizeof(INSTDATA));
- if (!lpInst)
- {
- #ifdef DEBUG
- OutputDebugString("Instance globals maxed outr");
- #endif
- return MAPI_E_NOT_ENOUGH_MEMORY;
- }
- if (lpInstPrev)
- lpInstPrev->next = lpInst;
- else
- *hInstHead = lpInst;
- lpInst->dwInstKey = (DWORD)LMGetCurrentA5();
- lpInst->dwPid = dwPid;
- lpInst->lpvInst[wDataSet] = pv;
- }
- }
- else
- {
- /* Deinstalling instance globals. Search and destroy. */
- if (lpInst == NULL || lpInst->lpvInst[wDataSet] == NULL)
- {
- #ifdef DEBUG
- OutputDebugString("No instance globals to resetr");
- #endif
- return MAPI_E_NOT_INITIALIZED;
- }
- /* The memory for <lpInst->lpvInst[wDataSet]> is disposed of */
- /* elsewhere. just as it was allocated elsewhere. */
- lpInst->lpvInst[wDataSet] = NULL;
- DisposeInstData(lpInstPrev, lpInst);
- }
- return 0;
- }
- LONG FAR PASCAL
- ScSetInstanceGlobals(LPVOID pv, WORD wDataSet)
- {
- return ScSetVerifyInstanceGlobals(pv, 0L, wDataSet);
- }
- BOOL FAR PASCAL
- FCleanupInstanceGlobals(WORD wID, DWORD dwData)
- {
- /*
- * This is no longer used.
- *
- */
- #ifdef DEBUG
- DebugStr("pCalled FCleanupInstanceGlobals : Empty function");
- #endif
- return 0;
- }
- #else /* !WIN16 && !_MAC */
- /* This is the entire 32-bit implementation for instance globals. */
- VOID FAR *pinstX = NULL;
- #endif /* WIN16 */