📄 obex.cpp
字号:
if(!pFactory)
return E_OUTOFMEMORY;
HRESULT hr = pFactory->QueryInterface(riid, ppv);
pFactory->Release();
return hr;
}
private:
LONG m_cRef;
};
template<typename T> ULONG STDMETHODCALLTYPE CFactory<T>::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
template<typename T> ULONG STDMETHODCALLTYPE CFactory<T>::Release()
{
SVSUTIL_ASSERT(m_cRef != 0xFFFFFFFF);
unsigned cRef = InterlockedDecrement(&m_cRef);
if(cRef != 0)
return cRef;
delete this;
return 0;
}
template<typename T> HRESULT STDMETHODCALLTYPE CFactory<T>::QueryInterface(REFIID riid, void** ppv)
{
if(riid == IID_IUnknown || riid == IID_IClassFactory)
{
*ppv = (IClassFactory *)this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CFactory<CObex>::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv)
{
if(pUnknownOuter != NULL)
return CLASS_E_NOAGGREGATION;
if (!ppv)
return E_POINTER;
*ppv = NULL;
HRESULT hr;
PREFAST_ASSERT(gpSynch);
gpSynch->Lock();
if (!g_pObex)
{
SVSUTIL_ASSERT(!g_pIRDATransport && !g_pBTHTransport); //their lifetimes depend on g_pObex
g_pIRDATransport = new CObexIRDATransport();
g_pBTHTransport = new CObexBTHTransport();
g_pObex = new CObex;
if (!g_pIRDATransport || !g_pBTHTransport || !g_pObex)
goto done;
}
else
g_pObex->AddRef();
hr = g_pObex->QueryInterface(riid, ppv);
g_pObex->Release();
gpSynch->Unlock();
return hr;
done:
if (g_pObex)
{
g_pObex->Release();
g_pObex = NULL;
}
if (g_pBTHTransport)
{
g_pBTHTransport->Release();
g_pBTHTransport = NULL;
}
if (g_pIRDATransport)
{
g_pIRDATransport->Release();
g_pIRDATransport = NULL;
}
gpSynch->Unlock();
return E_OUTOFMEMORY;;
}
HRESULT STDMETHODCALLTYPE
CFactory<CObexIRDATransport>::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv)
{
if(pUnknownOuter != NULL)
return CLASS_E_NOAGGREGATION;
gpSynch->Lock();
SVSUTIL_ASSERT(g_pObex && g_pIRDATransport);
HRESULT hr = g_pIRDATransport->QueryInterface(riid, ppv);
gpSynch->Unlock();
return hr;
}
HRESULT STDMETHODCALLTYPE
CFactory<CObexBTHTransport>::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv)
{
if(pUnknownOuter != NULL)
return CLASS_E_NOAGGREGATION;
gpSynch->Lock();
SVSUTIL_ASSERT(g_pObex && g_pBTHTransport);
HRESULT hr = g_pBTHTransport->QueryInterface(riid, ppv);
gpSynch->Unlock();
return hr;
}
template<typename T> HRESULT STDMETHODCALLTYPE
CFactory<T>::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv)
{
if(pUnknownOuter != NULL)
return CLASS_E_NOAGGREGATION;
T* t = new T;
if(!t)
return E_OUTOFMEMORY;
HRESULT hr = t->QueryInterface(riid, ppv);
t->Release();
return hr;
}
template<typename T> HRESULT STDMETHODCALLTYPE CFactory<T>::LockServer(BOOL bLock)
{
if(bLock)
g_cServerLocks++;
else
g_cServerLocks--;
return S_OK;
}
HRESULT STDMETHODCALLTYPE DllCanUnloadNow()
{
if(g_cServerLocks == 0 && g_cComponents == 0)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"DllCanUnloadNow -- unloading\n"));
return S_OK;
}
else
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"DllCanUnloadNow -- CANT UNLOAD\n"));
return S_FALSE;
}
}
HRESULT STDMETHODCALLTYPE DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
{
if(!ppv) return E_POINTER;
if(rclsid == CLSID_Obex)
return CFactory<CObex>::GetClassObject(riid, ppv);
if(rclsid == CLSID_HeaderCollection)
return CFactory<CHeaderCollection>::GetClassObject(riid, ppv);
if(rclsid == CLSID_PropertyBag)
return CFactory<CPropertyBag>::GetClassObject(riid, ppv);
if(rclsid == CLSID_IrdaTransport)
return CFactory<CObexIRDATransport>::GetClassObject(riid, ppv);
if(rclsid == CLSID_BthTransport)
return CFactory<CObexBTHTransport>::GetClassObject(riid, ppv);
if(rclsid == CLSID_IpTransport)
return CFactory<CObexTCPTransport>::GetClassObject(riid, ppv);
// repeat if statements here
return *ppv = 0, CLASS_E_CLASSNOTAVAILABLE;
}
HRESULT STDMETHODCALLTYPE DllRegisterServer()
{
HRESULT hRes = RegisterServer(L"ObexAPI.dll", CLSID_Obex, L"ObexAPI", L"Sum.OBEXAPI", L"Obex.OBEXAPI.1", L"Free");
if(SUCCEEDED(hRes))
hRes = RegisterServer(L"ObexAPI.dll", CLSID_HeaderCollection, L"ObexHeaderCollection", L"Obex.OBEXHeaderCollection", L"Sum.OBEXHeaderCollection.1", L"Free");
if(SUCCEEDED(hRes))
hRes = RegisterServer(L"ObexAPI.dll", CLSID_IrdaTransport, L"ObexIrdaTransport", L"Obex.ObexIrdaTransport", L"Sum.ObexIrdaTransport.1", L"Free");
if(SUCCEEDED(hRes))
hRes = RegisterServer(L"ObexAPI.dll", CLSID_BthTransport, L"ObexBthTransport", L"Obex.ObexBthTransport", L"Sum.ObexBthTransport.1", L"Free");
return hRes;
}
HRESULT STDMETHODCALLTYPE DllUnregisterServer()
{
return UnregisterServer(IID_IObex, L"Sum.OBEXAPI", L"Sum.OBEXAPI.1");
}
// Register the component in the registry.
HRESULT RegisterServer(const WCHAR * szModuleName, // DLL module handle
REFCLSID clsid, // Class ID
const WCHAR * szFriendlyName, // Friendly Name
const WCHAR * szVerIndProgID, // Programmatic
const WCHAR * szProgID, // IDs
const WCHAR * szThreadingModel) // ThreadingModel
{
// Get server location.
WCHAR szModule[512];
HMODULE hModule = GetModuleHandle(szModuleName);
DWORD dwResult = GetModuleFileName(hModule, szModule, sizeof(szModule)/sizeof(WCHAR));
SVSUTIL_ASSERT(dwResult != 0);
// Convert the CLSID into a char.
WCHAR szCLSID[CLSID_STRING_SIZE];
if(FAILED(CLSIDtochar(clsid, szCLSID, sizeof(szCLSID) / sizeof(WCHAR))))
return E_FAIL;
// Build the key CLSID\\{...}
WCHAR szKey[64];
wcscpy(szKey, L"CLSID\\");
wcscat(szKey, szCLSID);
// Add the CLSID to the registry.
setKeyAndValue(szKey, NULL, szFriendlyName);
// Add the server filename subkey under the CLSID key.
if(wcsstr(szModuleName, L".exe") == NULL)
{
setKeyAndValue(szKey, L"InprocServer32", szModule);
WCHAR szInproc[64];
wcscpy(szInproc, szKey);
wcscat(szInproc, L"\\InprocServer32");
setValueInKey(szInproc, L"ThreadingModel", szThreadingModel);
}
else
setKeyAndValue(szKey, L"LocalServer32", szModule);
// Add the ProgID subkey under the CLSID key.
setKeyAndValue(szKey, L"ProgID", szProgID);
// Add the version-independent ProgID subkey under CLSID key.
setKeyAndValue(szKey, L"VersionIndependentProgID", szVerIndProgID);
// Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
setKeyAndValue(szVerIndProgID, NULL, szFriendlyName);
setKeyAndValue(szVerIndProgID, L"CLSID", szCLSID);
setKeyAndValue(szVerIndProgID, L"CurVer", szProgID);
// Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
setKeyAndValue(szProgID, NULL, szFriendlyName);
setKeyAndValue(szProgID, L"CLSID", szCLSID);
return S_OK;
}
// Remove the component from the registry.
LONG UnregisterServer(REFCLSID clsid, // Class ID
const WCHAR * szVerIndProgID, // Programmatic
const WCHAR * szProgID) // IDs
{
// Convert the CLSID into a char.
WCHAR szCLSID[CLSID_STRING_SIZE];
if(FAILED(CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)/sizeof(WCHAR))))
return E_UNEXPECTED;
// Build the key CLSID\\{...}
WCHAR szKey[64];
wcscpy(szKey, L"CLSID\\");
wcscat(szKey, szCLSID);
// Delete the CLSID Key - CLSID\{...}
LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szKey);
SVSUTIL_ASSERT((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND)); // Subkey may not exist.
// Delete the version-independent ProgID Key.
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID);
SVSUTIL_ASSERT((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND)); // Subkey may not exist.
// Delete the ProgID key.
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID);
SVSUTIL_ASSERT((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND)); // Subkey may not exist.
return S_OK;
}
// Convert a CLSID to a char string.
HRESULT CLSIDtochar(REFCLSID clsid, WCHAR * szCLSID, unsigned int length)
{
SVSUTIL_ASSERT(length >= CLSID_STRING_SIZE);
// Get CLSID
LPOLESTR wszCLSID = NULL;
HRESULT hr = StringFromCLSID(clsid, &wszCLSID);
SVSUTIL_ASSERT(SUCCEEDED(hr));
if(SUCCEEDED(hr))
{
// Covert from wide characters to non-wide.
if(wcslen(wszCLSID) <= length) {
wcsncpy (szCLSID, wszCLSID, length);
}
else {
ASSERT(FALSE);
return E_FAIL;
}
// Free memory.
CoTaskMemFree(wszCLSID);
}
return hr;
}
// Delete a key and all of its descendents.
LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete
const WCHAR* lpszKeyChild) // Key to delete
{
// Open the child.
HKEY hKeyChild;
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0, KEY_ALL_ACCESS, &hKeyChild);
if(lRes != ERROR_SUCCESS)
return lRes;
// Enumerate all of the decendents of this child.
FILETIME time;
WCHAR szBuffer[256];
DWORD dwSize = 256;
while(RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == S_OK)
{
// Delete the decendents of this child.
lRes = recursiveDeleteKey(hKeyChild, szBuffer);
if(lRes != ERROR_SUCCESS)
{
// Cleanup before exiting.
RegCloseKey(hKeyChild);
return lRes;
}
dwSize = 256;
}
// Close the child.
RegCloseKey(hKeyChild);
// Delete this child.
return RegDeleteKey(hKeyParent, lpszKeyChild);
}
// Create a key and set its value.
BOOL setKeyAndValue(const WCHAR* szKey, const WCHAR* szSubkey, const WCHAR* szValue)
{
HKEY hKey;
WCHAR szKeyBuf[1024];
if(1024 <= wcslen(szKey))
return FALSE;
// Copy keyname into buffer.
wcsncpy(szKeyBuf, szKey, 1024 - 1);
szKeyBuf[1024 - 1] = 0;
// Add subkey name to buffer.
if(szSubkey != NULL)
{
wcscat(szKeyBuf, L"\\");
wcscat(szKeyBuf, szSubkey );
}
// Create and open key and subkey.
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szKeyBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
if(lResult != ERROR_SUCCESS)
return FALSE;
// Set the Value.
if(szValue != NULL)
RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)szValue, (wcslen(szValue)+1) * sizeof(WCHAR));
RegCloseKey(hKey);
return TRUE;
}
// Open a key and set a value.
BOOL setValueInKey(const WCHAR* szKey, const WCHAR* szNamedValue, const WCHAR* szValue)
{
HKEY hKey;
WCHAR szKeyBuf[1024];
if(1024 <= wcslen(szKey))
return FALSE;
// Copy keyname into buffer.
wcsncpy(szKeyBuf, szKey, 1024 - 1);
szKeyBuf[1024 - 1] = 0;
// Create and open key and subkey.
long lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKeyBuf, 0, KEY_SET_VALUE, &hKey);
if(lResult != ERROR_SUCCESS)
return FALSE;
// Set the Value.
if(szValue != NULL)
RegSetValueEx(hK
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -