📄 compobj.c
字号:
if (*ret) return S_OK;
/* do this outside the csOpenDllList to avoid creating a lock dependency on
* the loader lock */
hLibrary = LoadLibraryExW(library_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!hLibrary)
{
ERR("couldn't load in-process dll %s\n", debugstr_w(library_name));
/* failure: DLL could not be loaded */
return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
}
DllCanUnloadNow = (void *)GetProcAddress(hLibrary, "DllCanUnloadNow");
/* Note: failing to find DllCanUnloadNow is not a failure */
DllGetClassObject = (void *)GetProcAddress(hLibrary, "DllGetClassObject");
if (!DllGetClassObject)
{
/* failure: the dll did not export DllGetClassObject */
ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(library_name));
FreeLibrary(hLibrary);
return CO_E_DLLNOTFOUND;
}
EnterCriticalSection( &csOpenDllList );
*ret = COMPOBJ_DllList_Get(library_name);
if (*ret)
{
/* another caller to this function already added the dll while we
* weren't in the critical section */
FreeLibrary(hLibrary);
}
else
{
len = strlenW(library_name);
entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
if (entry)
entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
if (entry && entry->library_name)
{
memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR));
entry->library = hLibrary;
entry->refs = 1;
entry->DllCanUnloadNow = DllCanUnloadNow;
entry->DllGetClassObject = DllGetClassObject;
list_add_tail(&openDllList, &entry->entry);
}
else
{
hr = E_OUTOFMEMORY;
FreeLibrary(hLibrary);
}
*ret = entry;
}
LeaveCriticalSection( &csOpenDllList );
return hr;
}
static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name)
{
OpenDll *ptr;
OpenDll *ret = NULL;
EnterCriticalSection(&csOpenDllList);
LIST_FOR_EACH_ENTRY(ptr, &openDllList, OpenDll, entry)
{
if (!strcmpiW(library_name, ptr->library_name) &&
(InterlockedIncrement(&ptr->refs) != 1) /* entry is being destroy if == 1 */)
{
ret = ptr;
break;
}
}
LeaveCriticalSection(&csOpenDllList);
return ret;
}
/* pass FALSE for free_entry to release a reference without destroying the
* entry if it reaches zero or TRUE otherwise */
static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry)
{
if (!InterlockedDecrement(&entry->refs) && free_entry)
{
EnterCriticalSection(&csOpenDllList);
list_remove(&entry->entry);
LeaveCriticalSection(&csOpenDllList);
TRACE("freeing %p\n", entry->library);
FreeLibrary(entry->library);
HeapFree(GetProcessHeap(), 0, entry->library_name);
HeapFree(GetProcessHeap(), 0, entry);
}
}
/******************************************************************************
* CoBuildVersion [OLE32.@]
* CoBuildVersion [COMPOBJ.1]
*
* Gets the build version of the DLL.
*
* PARAMS
*
* RETURNS
* Current build version, hiword is majornumber, loword is minornumber
*/
DWORD WINAPI CoBuildVersion(void)
{
TRACE("Returning version %d, build %d.\n", rmm, rup);
return (rmm<<16)+rup;
}
/******************************************************************************
* CoInitialize [OLE32.@]
*
* Initializes the COM libraries by calling CoInitializeEx with
* COINIT_APARTMENTTHREADED, ie it enters a STA thread.
*
* PARAMS
* lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
*
* RETURNS
* Success: S_OK if not already initialized, S_FALSE otherwise.
* Failure: HRESULT code.
*
* SEE ALSO
* CoInitializeEx
*/
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
{
/*
* Just delegate to the newer method.
*/
return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
}
/******************************************************************************
* CoInitializeEx [OLE32.@]
*
* Initializes the COM libraries.
*
* PARAMS
* lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
* dwCoInit [I] One or more flags from the COINIT enumeration. See notes.
*
* RETURNS
* S_OK if successful,
* S_FALSE if this function was called already.
* RPC_E_CHANGED_MODE if a previous call to CoInitializeEx specified another
* threading model.
*
* NOTES
*
* The behavior used to set the IMalloc used for memory management is
* obsolete.
* The dwCoInit parameter must specify one of the following apartment
* threading models:
*| COINIT_APARTMENTTHREADED - A single-threaded apartment (STA).
*| COINIT_MULTITHREADED - A multi-threaded apartment (MTA).
* The parameter may also specify zero or more of the following flags:
*| COINIT_DISABLE_OLE1DDE - Don't use DDE for OLE1 support.
*| COINIT_SPEED_OVER_MEMORY - Trade memory for speed.
*
* SEE ALSO
* CoUninitialize
*/
HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
{
HRESULT hr = S_OK;
APARTMENT *apt;
TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit);
if (lpReserved!=NULL)
{
ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved);
}
/*
* Check the lock count. If this is the first time going through the initialize
* process, we have to initialize the libraries.
*
* And crank-up that lock count.
*/
if (InterlockedExchangeAdd(&s_COMLockCount,1)==0)
{
/*
* Initialize the various COM libraries and data structures.
*/
TRACE("() - Initializing the COM libraries\n");
/* we may need to defer this until after apartment initialisation */
RunningObjectTableImpl_Initialize();
}
if (!(apt = COM_CurrentInfo()->apt))
{
apt = apartment_get_or_create(dwCoInit);
if (!apt) return E_OUTOFMEMORY;
}
else if (!apartment_is_model(apt, dwCoInit))
{
/* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine
code then we are probably using the wrong threading model to implement that API. */
ERR("Attempt to change threading model of this apartment from %s to %s\n",
apt->multi_threaded ? "multi-threaded" : "apartment threaded",
dwCoInit & COINIT_APARTMENTTHREADED ? "apartment threaded" : "multi-threaded");
return RPC_E_CHANGED_MODE;
}
else
hr = S_FALSE;
COM_CurrentInfo()->inits++;
return hr;
}
/***********************************************************************
* CoUninitialize [OLE32.@]
*
* This method will decrement the refcount on the current apartment, freeing
* the resources associated with it if it is the last thread in the apartment.
* If the last apartment is freed, the function will additionally release
* any COM resources associated with the process.
*
* PARAMS
*
* RETURNS
* Nothing.
*
* SEE ALSO
* CoInitializeEx
*/
void WINAPI CoUninitialize(void)
{
struct oletls * info = COM_CurrentInfo();
LONG lCOMRefCnt;
TRACE("()\n");
/* will only happen on OOM */
if (!info) return;
/* sanity check */
if (!info->inits)
{
ERR("Mismatched CoUninitialize\n");
return;
}
if (!--info->inits)
{
apartment_release(info->apt);
info->apt = NULL;
}
/*
* Decrease the reference count.
* If we are back to 0 locks on the COM library, make sure we free
* all the associated data structures.
*/
lCOMRefCnt = InterlockedExchangeAdd(&s_COMLockCount,-1);
if (lCOMRefCnt==1)
{
TRACE("() - Releasing the COM libraries\n");
RunningObjectTableImpl_UnInitialize();
}
else if (lCOMRefCnt<1) {
ERR( "CoUninitialize() - not CoInitialized.\n" );
InterlockedExchangeAdd(&s_COMLockCount,1); /* restore the lock count. */
}
}
/******************************************************************************
* CoDisconnectObject [OLE32.@]
*
* Disconnects all connections to this object from remote processes. Dispatches
* pending RPCs while blocking new RPCs from occurring, and then calls
* IMarshal::DisconnectObject on the given object.
*
* Typically called when the object server is forced to shut down, for instance by
* the user.
*
* PARAMS
* lpUnk [I] The object whose stub should be disconnected.
* reserved [I] Reserved. Should be set to 0.
*
* RETURNS
* Success: S_OK.
* Failure: HRESULT code.
*
* SEE ALSO
* CoMarshalInterface, CoReleaseMarshalData, CoLockObjectExternal
*/
HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
{
HRESULT hr;
IMarshal *marshal;
APARTMENT *apt;
TRACE("(%p, 0x%08x)\n", lpUnk, reserved);
hr = IUnknown_QueryInterface(lpUnk, &IID_IMarshal, (void **)&marshal);
if (hr == S_OK)
{
hr = IMarshal_DisconnectObject(marshal, reserved);
IMarshal_Release(marshal);
return hr;
}
apt = COM_CurrentApt();
if (!apt)
return CO_E_NOTINITIALIZED;
apartment_disconnectobject(apt, lpUnk);
/* Note: native is pretty broken here because it just silently
* fails, without returning an appropriate error code if the object was
* not found, making apps think that the object was disconnected, when
* it actually wasn't */
return S_OK;
}
/******************************************************************************
* CoCreateGuid [OLE32.@]
*
* Simply forwards to UuidCreate in RPCRT4.
*
* PARAMS
* pguid [O] Points to the GUID to initialize.
*
* RETURNS
* Success: S_OK.
* Failure: HRESULT code.
*
* SEE ALSO
* UuidCreate
*/
HRESULT WINAPI CoCreateGuid(GUID *pguid)
{
return UuidCreate(pguid);
}
/******************************************************************************
* CLSIDFromString [OLE32.@]
* IIDFromString [OLE32.@]
*
* Converts a unique identifier from its string representation into
* the GUID struct.
*
* PARAMS
* idstr [I] The string representation of the GUID.
* id [O] GUID converted from the string.
*
* RETURNS
* S_OK on success
* CO_E_CLASSSTRING if idstr is not a valid CLSID
*
* SEE ALSO
* StringFromCLSID
*/
static HRESULT WINAPI __CLSIDFromString(LPCWSTR s, CLSID *id)
{
int i;
BYTE table[256];
if (!s) {
memset( id, 0, sizeof (CLSID) );
return S_OK;
}
/* validate the CLSID string */
if (strlenW(s) != 38)
return CO_E_CLASSSTRING;
if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}'))
return CO_E_CLASSSTRING;
for (i=1; i<37; i++) {
if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
if (!(((s[i] >= '0') && (s[i] <= '9')) ||
((s[i] >= 'a') && (s[i] <= 'f')) ||
((s[i] >= 'A') && (s[i] <= 'F'))))
return CO_E_CLASSSTRING;
}
TRACE("%s -> %p\n", debugstr_w(s), id);
/* quick lookup table */
memset(table, 0, 256);
for (i = 0; i < 10; i++) {
table['0' + i] = i;
}
for (i = 0; i < 6; i++) {
table['A' + i] = i+10;
table['a' + i] = i+10;
}
/* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
id->Data1 = (table[s[1]] << 28 | table[s[2]] << 24 | table[s[3]] << 20 | table[s[4]] << 16 |
table[s[5]] << 12 | table[s[6]] << 8 | table[s[7]] << 4 | table[s[8]]);
id->Data2 = table[s[10]] << 12 | table[s[11]] << 8 | table[s[12]] << 4 | table[s[13]];
id->Data3 = table[s[15]] << 12 | table[s[16]] << 8 | table[s[17]] << 4 | table[s[18]];
/* these are just sequential bytes */
id->Data4[0] = table[s[20]] << 4 | table[s[21]];
id->Data4[1] = table[s[22]] << 4 | table[s[23]];
id->Data4[2] = table[s[25]] << 4 | table[s[26]];
id->Data4[3] = table[s[27]] << 4 | table[s[28]];
id->Data4[4] = table[s[29]] << 4 | table[s[30]];
id->Data4[5] = table[s[31]] << 4 | table[s[32]];
id->Data4[6] = table[s[33]] << 4 | table[s[34]];
id->Data4[7] = table[s[35]] << 4 | table[s[36]];
return S_OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -