4862 lines
141 KiB
C++
4862 lines
141 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1998.
|
|
//
|
|
// File: Reg.cpp
|
|
//
|
|
// Contents: Registration routines
|
|
//
|
|
// Classes:
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
// 11-18-97 susia Added Autosync and user reg key functions
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "precomp.h"
|
|
|
|
#ifdef _SENS
|
|
#include <eventsys.h> // include event system
|
|
#include <sens.h>
|
|
#include <sensevts.h>
|
|
#endif // _SENS
|
|
|
|
// temporariy define new mstask flag in case hasn't
|
|
// propogated to sdk\inc
|
|
|
|
#ifndef TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
|
|
#define TASK_FLAG_RUN_ONLY_IF_LOGGED_ON (0x2000)
|
|
#endif // TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
|
|
extern HINSTANCE g_hmodThisDll; // Handle to this DLL itself.
|
|
extern OSVERSIONINFOA g_OSVersionInfo;
|
|
extern CRITICAL_SECTION g_DllCriticalSection; // Global Critical Section for this DLL
|
|
|
|
// only return success on NT 5.0
|
|
|
|
BOOL GetUserDefaultSecurityAttribs(SECURITY_ATTRIBUTES *psa
|
|
,PSECURITY_DESCRIPTOR psd,
|
|
PACL *ppOutAcl)
|
|
{
|
|
BOOL bRetVal;
|
|
int cbAcl;
|
|
PACL pAcl = NULL;
|
|
PSID pInteractiveUserSid = NULL;
|
|
PSID pLocalSystemSid = NULL;
|
|
PSID pAdminsSid = NULL;
|
|
SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
*ppOutAcl = NULL;
|
|
|
|
bRetVal = FALSE;
|
|
|
|
// in the structure.
|
|
|
|
bRetVal = InitializeSecurityDescriptor(
|
|
psd, // Pointer to SD
|
|
SECURITY_DESCRIPTOR_REVISION // SD revision
|
|
);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"Unable to Init SecurityDescriptor");
|
|
goto errRtn;
|
|
}
|
|
|
|
// setup acls.
|
|
|
|
bRetVal = AllocateAndInitializeSid(
|
|
&LocalSystemAuthority, // Pointer to identifier authority
|
|
1, // Count of subauthority
|
|
SECURITY_INTERACTIVE_RID, // Subauthority 0
|
|
0, // Subauthority 1
|
|
0, // Subauthority 2
|
|
0, // Subauthority 3
|
|
0, // Subauthority 4
|
|
0, // Subauthority 5
|
|
0, // Subauthority 6
|
|
0, // Subauthority 7
|
|
&pInteractiveUserSid // pointer to pointer to SID
|
|
);
|
|
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"Alocate sid failed");
|
|
goto errRtn;
|
|
}
|
|
|
|
bRetVal = AllocateAndInitializeSid(
|
|
&LocalSystemAuthority, // Pointer to identifier authority
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0,
|
|
0, // Subauthority 3
|
|
0, // Subauthority 4
|
|
0, // Subauthority 5
|
|
0, // Subauthority 6
|
|
0, // Subauthority 7
|
|
&pAdminsSid // pointer to pointer to SID
|
|
);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"Alocate sid failed");
|
|
goto errRtn;
|
|
}
|
|
|
|
|
|
bRetVal = AllocateAndInitializeSid(
|
|
&LocalSystemAuthority,// Pointer to identifier authority
|
|
1, // Count of subauthority
|
|
SECURITY_LOCAL_SYSTEM_RID, // Subauthority 0
|
|
0, // Subauthority 1
|
|
0, // Subauthority 2
|
|
0, // Subauthority 3
|
|
0, // Subauthority 4
|
|
0, // Subauthority 5
|
|
0, // Subauthority 6
|
|
0, // Subauthority 7
|
|
&pLocalSystemSid // pointer to pointer to SID
|
|
);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"Alocate sid failed");
|
|
goto errRtn;
|
|
}
|
|
|
|
cbAcl = sizeof (ACL)
|
|
+ 3 * sizeof (ACCESS_ALLOWED_ACE)
|
|
+ GetLengthSid(pInteractiveUserSid)
|
|
+ GetLengthSid(pLocalSystemSid)
|
|
+ GetLengthSid(pAdminsSid);
|
|
|
|
pAcl = (PACL) new char[cbAcl];
|
|
|
|
if (NULL == pAcl)
|
|
{
|
|
bRetVal = FALSE;
|
|
|
|
AssertSz(0,"unable to alloc ACL");
|
|
goto errRtn;
|
|
}
|
|
|
|
bRetVal = InitializeAcl(
|
|
pAcl, // Pointer to the ACL
|
|
cbAcl, // Size of ACL
|
|
ACL_REVISION // Revision level of ACL
|
|
);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"InitAcl failed");
|
|
goto errRtn;
|
|
}
|
|
|
|
|
|
bRetVal = AddAccessAllowedAce(
|
|
pAcl, // Pointer to the ACL
|
|
ACL_REVISION, // ACL revision level
|
|
SPECIFIC_RIGHTS_ALL | GENERIC_READ | DELETE , // Access Mask
|
|
pInteractiveUserSid // Pointer to SID
|
|
);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"AddAccessAllowed Failed");
|
|
goto errRtn;
|
|
}
|
|
|
|
|
|
bRetVal = AddAccessAllowedAce(
|
|
pAcl, // Pointer to the ACL
|
|
ACL_REVISION, // ACL revision level
|
|
GENERIC_ALL, // Access Mask
|
|
pAdminsSid // Pointer to SID
|
|
);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"AddAccessAllowed Failed");
|
|
goto errRtn;
|
|
}
|
|
|
|
bRetVal = AddAccessAllowedAce(
|
|
pAcl, // Pointer to the ACL
|
|
ACL_REVISION, // ACL revision level
|
|
GENERIC_ALL, // Access Mask
|
|
pLocalSystemSid // Pointer to SID
|
|
);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"AddAccessAllowed Failed");
|
|
goto errRtn;
|
|
}
|
|
|
|
bRetVal = SetSecurityDescriptorDacl(psd,TRUE,pAcl,FALSE);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
AssertSz(0,"SetSecurityDescirptorDacl Failed");
|
|
goto errRtn;
|
|
}
|
|
|
|
psa->nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
psa->lpSecurityDescriptor = psd;
|
|
psa->bInheritHandle = FALSE;
|
|
|
|
errRtn:
|
|
|
|
if (pInteractiveUserSid)
|
|
{
|
|
FreeSid(pInteractiveUserSid);
|
|
}
|
|
|
|
if (pLocalSystemSid)
|
|
{
|
|
FreeSid(pLocalSystemSid);
|
|
}
|
|
|
|
if (pAdminsSid)
|
|
{
|
|
FreeSid(pAdminsSid);
|
|
}
|
|
|
|
//
|
|
// On failure, we clean the ACL up. On success, the caller cleans
|
|
// it up after using it.
|
|
//
|
|
if (FALSE == bRetVal)
|
|
{
|
|
if (pAcl)
|
|
{
|
|
delete pAcl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Assert(pAcl);
|
|
*ppOutAcl = pAcl;
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
const WCHAR SZ_USERSIDKEY[] = TEXT("SID");
|
|
|
|
// calls regOpen or create based on fCreate param
|
|
|
|
|
|
LONG RegGetKeyHelper(HKEY hkey,LPCWSTR pszKey,REGSAM samDesired,BOOL fCreate,
|
|
HKEY *phkResult,DWORD *pdwDisposition)
|
|
{
|
|
LONG lRet = -1;
|
|
|
|
Assert(pdwDisposition);
|
|
|
|
*pdwDisposition = 0;
|
|
|
|
if (fCreate)
|
|
{
|
|
lRet = RegCreateKeyEx(hkey,pszKey,0,NULL,REG_OPTION_NON_VOLATILE,
|
|
samDesired,NULL,phkResult,pdwDisposition);
|
|
}
|
|
else
|
|
{
|
|
lRet = RegOpenKeyEx(hkey,pszKey,0,samDesired,phkResult);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
*pdwDisposition = REG_OPENED_EXISTING_KEY;
|
|
}
|
|
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
|
|
|
|
// called to create a new UserKey or subkey
|
|
LONG RegCreateUserSubKey(
|
|
HKEY hKey,
|
|
LPCWSTR lpSubKey,
|
|
REGSAM samDesired,
|
|
PHKEY phkResult)
|
|
{
|
|
LONG lRet;
|
|
DWORD dwDisposition;
|
|
|
|
lRet = RegCreateKeyEx(hKey,lpSubKey,0,NULL,REG_OPTION_NON_VOLATILE,
|
|
samDesired,NULL,phkResult,&dwDisposition);
|
|
|
|
if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
// !! if subkey contains \\ don't traverse back through the list
|
|
|
|
if ( (ERROR_SUCCESS == lRet) && (REG_CREATED_NEW_KEY == dwDisposition))
|
|
{
|
|
HKEY hKeySecurity;
|
|
SECURITY_ATTRIBUTES sa;
|
|
SECURITY_DESCRIPTOR sd;
|
|
PACL pOutAcl;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hKey,
|
|
lpSubKey,
|
|
REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) )
|
|
{
|
|
if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl))
|
|
{
|
|
|
|
RegSetKeySecurity(hKeySecurity,
|
|
(SECURITY_INFORMATION) DACL_SECURITY_INFORMATION,
|
|
&sd);
|
|
|
|
delete pOutAcl;
|
|
}
|
|
|
|
RegCloseKey(hKeySecurity);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
return lRet;
|
|
}
|
|
|
|
|
|
STDAPI_(HKEY) RegOpenUserKey(HKEY hkeyParent,REGSAM samDesired,BOOL fCreate,BOOL fCleanReg)
|
|
{
|
|
TCHAR pszDomainAndUser[MAX_DOMANDANDMACHINENAMESIZE];
|
|
HKEY hKeyUser;
|
|
BOOL fSetUserSid = FALSE;
|
|
WCHAR szUserSID[MAX_PATH + 1];
|
|
DWORD dwType;
|
|
DWORD dwDisposition;
|
|
LONG ret;
|
|
|
|
|
|
GetDefaultDomainAndUserName(pszDomainAndUser,TEXT("_"),MAX_DOMANDANDMACHINENAMESIZE);
|
|
|
|
// If suppose to clean the settings for the user/ delete the key
|
|
if (fCleanReg)
|
|
{
|
|
RegDeleteKeyNT(hkeyParent,pszDomainAndUser);
|
|
}
|
|
|
|
|
|
if (ERROR_SUCCESS != (ret = RegGetKeyHelper(hkeyParent,pszDomainAndUser,samDesired,fCreate,
|
|
&hKeyUser,&dwDisposition)))
|
|
{
|
|
hKeyUser = NULL;
|
|
}
|
|
// On NT 5.0 Verify sid matches and if doesn't blow away any settings.
|
|
// then create again.
|
|
|
|
if (hKeyUser && (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId))
|
|
{
|
|
WCHAR szRegSID[MAX_PATH + 1];
|
|
DWORD dwDataSize;
|
|
|
|
dwDataSize = ARRAY_SIZE(szRegSID);
|
|
if (ERROR_SUCCESS !=RegQueryValueEx(hKeyUser,
|
|
SZ_USERSIDKEY,NULL, &dwType,
|
|
(LPBYTE) szRegSID, &dwDataSize))
|
|
{
|
|
fSetUserSid = TRUE;
|
|
|
|
// if have to set the sid need to make sure openned
|
|
// with set Value and if didn't close key and
|
|
// let create re-open it with the desired access.
|
|
|
|
if (!(samDesired & KEY_SET_VALUE))
|
|
{
|
|
RegCloseKey(hKeyUser);
|
|
hKeyUser = NULL;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwDataSize = ARRAY_SIZE(szUserSID);
|
|
if (GetUserTextualSid(szUserSID, &dwDataSize))
|
|
{
|
|
if (lstrcmp(szRegSID, szUserSID))
|
|
{
|
|
// if don't have access privledges
|
|
// to delete the User this will fail.
|
|
// may want a call into SENS to delete the
|
|
// User Key on Failure.
|
|
RegCloseKey(hKeyUser);
|
|
hKeyUser = NULL; // set to NULL so check below fails.
|
|
RegDeleteKeyNT(hkeyParent,pszDomainAndUser);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
|
|
if (ERROR_SUCCESS != (ret = RegGetKeyHelper(hkeyParent,pszDomainAndUser,
|
|
samDesired,fCreate,
|
|
&hKeyUser,&dwDisposition)))
|
|
{
|
|
hKeyUser = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (REG_CREATED_NEW_KEY == dwDisposition)
|
|
{
|
|
fSetUserSid = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// on creation setup the security
|
|
if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
|
|
if ( (ERROR_SUCCESS == ret) && (REG_CREATED_NEW_KEY == dwDisposition))
|
|
{
|
|
HKEY hKeySecurity;
|
|
SECURITY_ATTRIBUTES sa;
|
|
SECURITY_DESCRIPTOR sd;
|
|
PACL pOutAcl;
|
|
|
|
// !! should have own call for sync type key security
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkeyParent,pszDomainAndUser,
|
|
REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) )
|
|
{
|
|
if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl))
|
|
{
|
|
|
|
RegSetKeySecurity(hKeySecurity,
|
|
(SECURITY_INFORMATION) DACL_SECURITY_INFORMATION,
|
|
&sd);
|
|
|
|
delete pOutAcl;
|
|
}
|
|
|
|
RegCloseKey(hKeySecurity);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// setup the User sid.
|
|
// depends on key being openned with KEY_SET_VALUE
|
|
if (hKeyUser && fSetUserSid && (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)
|
|
&& (samDesired & KEY_SET_VALUE))
|
|
{
|
|
WCHAR szUserSID[MAX_PATH + 1];
|
|
DWORD dwDataSize;
|
|
|
|
dwDataSize = ARRAY_SIZE(szUserSID);
|
|
|
|
if (GetUserTextualSid(szUserSID, &dwDataSize))
|
|
{
|
|
DWORD dwType = REG_SZ;
|
|
|
|
RegSetValueEx (hKeyUser,SZ_USERSIDKEY,NULL,
|
|
dwType,
|
|
(LPBYTE) szUserSID,
|
|
(lstrlen(szUserSID) + 1)*sizeof(WCHAR));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return hKeyUser;
|
|
|
|
}
|
|
|
|
STDAPI_(HKEY) RegGetSyncTypeKey(DWORD dwSyncType,REGSAM samDesired,BOOL fCreate)
|
|
{
|
|
HKEY hKeySyncType;
|
|
LPCWSTR pszKey;
|
|
LONG ret;
|
|
DWORD dwDisposition;
|
|
|
|
// get appropriate key to open based on sync type
|
|
|
|
switch(dwSyncType)
|
|
{
|
|
case SYNCTYPE_MANUAL:
|
|
pszKey = MANUALSYNC_REGKEY;
|
|
break;
|
|
case SYNCTYPE_AUTOSYNC:
|
|
pszKey = AUTOSYNC_REGKEY;
|
|
break;
|
|
case SYNCTYPE_IDLE:
|
|
pszKey = IDLESYNC_REGKEY;
|
|
break;
|
|
case SYNCTYPE_SCHEDULED:
|
|
pszKey = SCHEDSYNC_REGKEY;
|
|
break;
|
|
case SYNCTYPE_PROGRESS:
|
|
pszKey = PROGRESS_REGKEY;
|
|
break;
|
|
default:
|
|
AssertSz(0,"Unknown SyncType");
|
|
pszKey = NULL;
|
|
break;
|
|
}
|
|
|
|
if (NULL == pszKey)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// first try to open the existing key
|
|
if (ERROR_SUCCESS != (ret = RegGetKeyHelper(HKEY_LOCAL_MACHINE,pszKey,samDesired,fCreate,
|
|
&hKeySyncType,&dwDisposition)))
|
|
{
|
|
// if can't open key try to create
|
|
|
|
if (ERROR_ACCESS_DENIED == ret )
|
|
{
|
|
// if access denied, call sens to reset
|
|
// the security on the topelevel keys.
|
|
SyncMgrExecCmd_ResetRegSecurity();
|
|
|
|
ret = RegGetKeyHelper(HKEY_LOCAL_MACHINE,pszKey,samDesired,fCreate,
|
|
&hKeySyncType,&dwDisposition);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != ret)
|
|
{
|
|
hKeySyncType = NULL;
|
|
}
|
|
}
|
|
|
|
if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
|
|
if ( (ERROR_SUCCESS == ret) && (REG_CREATED_NEW_KEY == dwDisposition))
|
|
{
|
|
HKEY hKeySecurity;
|
|
SECURITY_ATTRIBUTES sa;
|
|
SECURITY_DESCRIPTOR sd;
|
|
PACL pOutAcl;
|
|
|
|
// !! should have own call for sync type key security
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,pszKey,
|
|
REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) )
|
|
{
|
|
if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl))
|
|
{
|
|
|
|
RegSetKeySecurity(hKeySecurity,
|
|
(SECURITY_INFORMATION) DACL_SECURITY_INFORMATION,
|
|
&sd);
|
|
|
|
delete pOutAcl;
|
|
}
|
|
|
|
RegCloseKey(hKeySecurity);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hKeySyncType;
|
|
}
|
|
|
|
|
|
STDAPI_(HKEY) RegGetCurrentUserKey(DWORD dwSyncType,REGSAM samDesired,BOOL fCreate)
|
|
{
|
|
HKEY hKeySyncType;
|
|
HKEY hKeyUser = NULL;
|
|
|
|
hKeySyncType = RegGetSyncTypeKey(dwSyncType,samDesired ,fCreate);
|
|
|
|
if (hKeySyncType)
|
|
{
|
|
hKeyUser = RegOpenUserKey(hKeySyncType,samDesired,fCreate,FALSE /* fClean */);
|
|
RegCloseKey(hKeySyncType);
|
|
}
|
|
|
|
return hKeyUser;
|
|
}
|
|
|
|
|
|
// tries to open and set security if necessary on the handler keys.
|
|
|
|
STDAPI_(HKEY) RegGetHandlerTopLevelKey(REGSAM samDesired)
|
|
{
|
|
HKEY hKeyTopLevel;
|
|
LONG ret;
|
|
DWORD dwDisposition;
|
|
|
|
// if open failed then try a create.
|
|
if (ERROR_SUCCESS != (ret = RegCreateKeyEx (HKEY_LOCAL_MACHINE,HANDLERS_REGKEY,0, NULL,
|
|
REG_OPTION_NON_VOLATILE,samDesired,NULL,
|
|
&hKeyTopLevel,
|
|
&dwDisposition)))
|
|
{
|
|
|
|
// if got an access denige on the handlers key
|
|
// call sens to reset.
|
|
if (ERROR_ACCESS_DENIED == ret )
|
|
{
|
|
// if access denied, call sens to reset
|
|
// the security on the topelevel keys.
|
|
// and try again
|
|
SyncMgrExecCmd_ResetRegSecurity();
|
|
|
|
ret = RegCreateKeyEx (HKEY_LOCAL_MACHINE,HANDLERS_REGKEY,0, NULL,
|
|
REG_OPTION_NON_VOLATILE,samDesired,NULL,
|
|
&hKeyTopLevel,
|
|
&dwDisposition);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != ret)
|
|
{
|
|
hKeyTopLevel = NULL;
|
|
}
|
|
}
|
|
|
|
if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
|
|
if ( (ERROR_SUCCESS == ret) && (REG_CREATED_NEW_KEY == dwDisposition))
|
|
{
|
|
HKEY hKeySecurity;
|
|
SECURITY_ATTRIBUTES sa;
|
|
SECURITY_DESCRIPTOR sd;
|
|
PACL pOutAcl;
|
|
|
|
// !! should have own call for toplevel handler key security
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
HANDLERS_REGKEY,
|
|
REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) )
|
|
{
|
|
if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl))
|
|
{
|
|
|
|
RegSetKeySecurity(hKeySecurity,
|
|
(SECURITY_INFORMATION) DACL_SECURITY_INFORMATION,
|
|
&sd);
|
|
|
|
delete pOutAcl;
|
|
}
|
|
|
|
RegCloseKey(hKeySecurity);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hKeyTopLevel;
|
|
|
|
}
|
|
|
|
STDAPI_(HKEY) RegGetHandlerKey(HKEY hkeyParent,LPCWSTR pszHandlerClsid,REGSAM samDesired,
|
|
BOOL fCreate)
|
|
{
|
|
HKEY hKeyHandler = NULL;
|
|
LRESULT lRet;
|
|
DWORD dwDisposition;
|
|
|
|
|
|
if (ERROR_SUCCESS != (lRet = RegGetKeyHelper(hkeyParent,pszHandlerClsid,samDesired,
|
|
fCreate,&hKeyHandler,&dwDisposition)))
|
|
{
|
|
hKeyHandler = NULL;
|
|
}
|
|
|
|
if (NULL == hKeyHandler)
|
|
{
|
|
|
|
// if got an access denied call sens to unlock
|
|
if (ERROR_ACCESS_DENIED == lRet )
|
|
{
|
|
// if access denied, call sens to reset
|
|
// the security on the topelevel keys.
|
|
// and try again
|
|
SyncMgrExecCmd_ResetRegSecurity();
|
|
|
|
lRet = RegGetKeyHelper(hkeyParent,pszHandlerClsid,samDesired,
|
|
fCreate,&hKeyHandler,&dwDisposition);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
hKeyHandler = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
|
|
if ( (ERROR_SUCCESS == lRet) && (REG_CREATED_NEW_KEY == dwDisposition))
|
|
{
|
|
HKEY hKeySecurity;
|
|
SECURITY_ATTRIBUTES sa;
|
|
SECURITY_DESCRIPTOR sd;
|
|
PACL pOutAcl;
|
|
|
|
// !! should have own call for handler key security
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkeyParent,
|
|
pszHandlerClsid,
|
|
REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) )
|
|
{
|
|
if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl))
|
|
{
|
|
|
|
RegSetKeySecurity(hKeySecurity,
|
|
(SECURITY_INFORMATION) DACL_SECURITY_INFORMATION,
|
|
&sd);
|
|
|
|
delete pOutAcl;
|
|
}
|
|
|
|
RegCloseKey(hKeySecurity);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hKeyHandler;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: DWORD RegDeleteKeyNT(HKEY hStartKey , LPTSTR pKeyName )
|
|
|
|
Summary: Recursively delete a key on NT
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
|
|
STDAPI_(DWORD) RegDeleteKeyNT(HKEY hStartKey , LPCWSTR pKeyName )
|
|
{
|
|
DWORD dwRtn, dwSubKeyLength;
|
|
LPTSTR pSubKey = NULL;
|
|
TCHAR szSubKey[MAX_KEY_LENGTH]; // (256) this should be dynamic.
|
|
HKEY hkey;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
// do not allow NULL or empty key name
|
|
if ( pKeyName && lstrlen(pKeyName))
|
|
{
|
|
if( (dwRtn=RegOpenKeyEx(hStartKey,pKeyName,
|
|
0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hkey )) == ERROR_SUCCESS)
|
|
{
|
|
while (dwRtn == ERROR_SUCCESS )
|
|
{
|
|
dwSubKeyLength = MAX_KEY_LENGTH;
|
|
dwRtn=RegEnumKeyEx(
|
|
hkey,
|
|
0, // always index zero
|
|
szSubKey,
|
|
&dwSubKeyLength,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if(dwRtn == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
dwRtn = RegDeleteKey(hStartKey, pKeyName);
|
|
break;
|
|
}
|
|
else if(dwRtn == ERROR_SUCCESS)
|
|
dwRtn=RegDeleteKeyNT(hkey, szSubKey);
|
|
}
|
|
RegCloseKey(hkey);
|
|
// Do not save return code because error
|
|
// has already occurred
|
|
}
|
|
}
|
|
else
|
|
dwRtn = ERROR_BADKEY;
|
|
|
|
CMutexRegistry.Leave();
|
|
return dwRtn;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegGetProgressDetailsState()
|
|
|
|
Summary: Gets the expanded or collapsed user preference for the progress dialog
|
|
and the pushpin preference
|
|
|
|
Returns: Returns TRUE if succeeded, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegGetProgressDetailsState(REFCLSID clsidDlg,BOOL *pfPushPin, BOOL *pfExpanded)
|
|
{
|
|
SCODE sc = S_FALSE;
|
|
HKEY hkeyUserProgress,hkeyclsidDlg;
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
WCHAR wszCLSID[GUID_SIZE + 1];
|
|
|
|
if (0 == StringFromGUID2(clsidDlg, wszCLSID, GUID_SIZE))
|
|
{
|
|
AssertSz(0,"Unable to make Guid a String");
|
|
return FALSE;
|
|
}
|
|
|
|
//Prgress dialog defaults to collapsed, pushpin out
|
|
*pfExpanded = FALSE;
|
|
*pfPushPin = FALSE;
|
|
|
|
hkeyUserProgress = RegGetCurrentUserKey(SYNCTYPE_PROGRESS,KEY_READ,FALSE);
|
|
|
|
if (hkeyUserProgress)
|
|
{
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkeyUserProgress,wszCLSID,0,KEY_READ,
|
|
&hkeyclsidDlg))
|
|
{
|
|
RegQueryValueEx(hkeyclsidDlg,TEXT("Expanded"),NULL, &dwType,
|
|
(LPBYTE) pfExpanded,
|
|
&dwDataSize);
|
|
dwType = REG_DWORD ;
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
RegQueryValueEx(hkeyclsidDlg,TEXT("PushPin"),NULL, &dwType,
|
|
(LPBYTE) pfPushPin,
|
|
&dwDataSize);
|
|
RegCloseKey(hkeyclsidDlg);
|
|
|
|
sc = S_OK;
|
|
}
|
|
|
|
|
|
RegCloseKey(hkeyUserProgress);
|
|
}
|
|
|
|
if (sc == S_OK)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegSetProgressDetailsState(BOOL fExpanded)
|
|
|
|
Summary: Sets the expanded or collapsed user preference for the progress dialog
|
|
|
|
Returns: Returns TRUE if succeeded, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegSetProgressDetailsState(REFCLSID clsidDlg,BOOL fPushPin, BOOL fExpanded)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hkeyUserProgress,hkeyclsidDlg;
|
|
WCHAR wszCLSID[GUID_SIZE + 1];
|
|
|
|
|
|
if (0 == StringFromGUID2(clsidDlg, wszCLSID, GUID_SIZE))
|
|
{
|
|
AssertSz(0,"Unable to make Guid a String");
|
|
return FALSE;
|
|
}
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
hkeyUserProgress = RegGetCurrentUserKey(SYNCTYPE_PROGRESS,KEY_WRITE | KEY_READ,TRUE);
|
|
|
|
if (hkeyUserProgress)
|
|
{
|
|
|
|
if (ERROR_SUCCESS == RegCreateUserSubKey(hkeyUserProgress,wszCLSID,
|
|
KEY_WRITE | KEY_READ,
|
|
&hkeyclsidDlg))
|
|
{
|
|
|
|
fResult = TRUE;
|
|
|
|
if (ERROR_SUCCESS != RegSetValueEx(hkeyclsidDlg,TEXT("Expanded"),NULL, REG_DWORD,
|
|
(LPBYTE) &(fExpanded),
|
|
sizeof(DWORD)))
|
|
{
|
|
fResult = FALSE;
|
|
}
|
|
|
|
|
|
if (ERROR_SUCCESS == RegSetValueEx(hkeyclsidDlg,TEXT("PushPin"),NULL, REG_DWORD,
|
|
(LPBYTE) &(fPushPin),
|
|
sizeof(DWORD)))
|
|
{
|
|
fResult = FALSE;
|
|
}
|
|
|
|
RegCloseKey(hkeyclsidDlg);
|
|
}
|
|
|
|
RegCloseKey(hkeyUserProgress);
|
|
|
|
}
|
|
|
|
CMutexRegistry.Leave();
|
|
return fResult;
|
|
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegGetSyncItemSettings( DWORD dwSyncType,
|
|
CLSID clsidHandler,
|
|
SYNCMGRITEMID ItemId,
|
|
const TCHAR *pszConnectionName,
|
|
DWORD *pdwCheckState,
|
|
DWORD dwDefaultCheckState,
|
|
TCHAR *pszSchedName)
|
|
|
|
Summary: Gets the settings per handler, itemID, and connection name.
|
|
If no selections on this connection, the default is ?
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegGetSyncItemSettings( DWORD dwSyncType,
|
|
CLSID clsidHandler,
|
|
SYNCMGRITEMID ItemId,
|
|
const TCHAR *pszConnectionName,
|
|
DWORD *pdwCheckState,
|
|
DWORD dwDefaultCheckState,
|
|
TCHAR *pszSchedName)
|
|
{
|
|
HKEY hKeyUser;
|
|
|
|
*pdwCheckState = dwDefaultCheckState;
|
|
|
|
// special case schedule
|
|
if (SYNCTYPE_SCHEDULED == dwSyncType)
|
|
{
|
|
// items are always turned off by default and if no schedule name
|
|
// don't bother.
|
|
*pdwCheckState = FALSE;
|
|
if (!pszSchedName)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// open the user key for the type
|
|
hKeyUser = RegGetCurrentUserKey(dwSyncType,KEY_READ,FALSE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// for a schedule we need to go ahead and open up the schedule name
|
|
// key
|
|
|
|
HKEY hKeySchedule = NULL;
|
|
|
|
// Review if want GetCurrentUserKey to Handle this.
|
|
if (SYNCTYPE_SCHEDULED == dwSyncType)
|
|
{
|
|
if (ERROR_SUCCESS != RegOpenKeyEx((hKeyUser),
|
|
pszSchedName,0,KEY_READ,
|
|
&hKeySchedule))
|
|
{
|
|
hKeySchedule = NULL;
|
|
RegCloseKey(hKeyUser);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL fResult;
|
|
|
|
fResult = RegLookupSettings(hKeySchedule ? hKeySchedule : hKeyUser,
|
|
clsidHandler,
|
|
ItemId,
|
|
pszConnectionName,
|
|
pdwCheckState);
|
|
|
|
if (hKeySchedule)
|
|
{
|
|
RegCloseKey(hKeySchedule);
|
|
}
|
|
|
|
if (hKeyUser)
|
|
{
|
|
RegCloseKey(hKeyUser);
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegSetSyncItemSettings( DWORD dwSyncType,
|
|
CLSID clsidHandler,
|
|
SYNCMGRITEMID ItemId,
|
|
const TCHAR *pszConnectionName,
|
|
DWORD dwCheckState,
|
|
TCHAR *pszSchedName)
|
|
|
|
Summary: Sets the settings per handler, itemID, and connection name.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegSetSyncItemSettings( DWORD dwSyncType,
|
|
CLSID clsidHandler,
|
|
SYNCMGRITEMID ItemId,
|
|
const TCHAR *pszConnectionName,
|
|
DWORD dwCheckState,
|
|
TCHAR *pszSchedName)
|
|
{
|
|
HKEY hKeyUser;
|
|
|
|
|
|
if (SYNCTYPE_SCHEDULED == dwSyncType)
|
|
{
|
|
if (NULL == pszSchedName)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// open the user key for the type
|
|
hKeyUser = RegGetCurrentUserKey(dwSyncType,KEY_WRITE | KEY_READ,TRUE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// for a schedule we need to go ahead and open up the schedule name
|
|
// key
|
|
|
|
HKEY hKeySchedule = NULL;
|
|
|
|
if (SYNCTYPE_SCHEDULED == dwSyncType)
|
|
{
|
|
if (ERROR_SUCCESS != RegCreateUserSubKey(hKeyUser,
|
|
pszSchedName,KEY_WRITE | KEY_READ,
|
|
&hKeySchedule))
|
|
{
|
|
hKeySchedule = NULL;
|
|
RegCloseKey(hKeyUser);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL fResult;
|
|
|
|
fResult = RegWriteOutSettings(hKeySchedule ? hKeySchedule : hKeyUser,
|
|
clsidHandler,
|
|
ItemId,
|
|
pszConnectionName,
|
|
dwCheckState);
|
|
|
|
if (hKeySchedule)
|
|
{
|
|
RegCloseKey(hKeySchedule);
|
|
}
|
|
|
|
if (hKeyUser)
|
|
{
|
|
RegCloseKey(hKeyUser);
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegQueryLoadHandlerOnEvent( )
|
|
|
|
Summary: Determines if there is any reason to load this handler
|
|
for the specified event and Connection
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegQueryLoadHandlerOnEvent(TCHAR *pszClsid,DWORD dwSyncFlags,
|
|
TCHAR *pConnectionName)
|
|
{
|
|
BOOL fLoadHandler = FALSE;
|
|
DWORD dwSyncType;
|
|
|
|
switch(dwSyncFlags & SYNCMGRFLAG_EVENTMASK)
|
|
{
|
|
case SYNCMGRFLAG_CONNECT:
|
|
case SYNCMGRFLAG_PENDINGDISCONNECT:
|
|
{
|
|
dwSyncType = SYNCTYPE_AUTOSYNC;
|
|
}
|
|
break;
|
|
case SYNCMGRFLAG_IDLE:
|
|
{
|
|
dwSyncType = SYNCTYPE_IDLE;
|
|
}
|
|
break;
|
|
default:
|
|
AssertSz(0,"Unknown SyncType");
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
// walk done the list openning keys.
|
|
HKEY hkeySyncType;
|
|
|
|
if (hkeySyncType = RegGetCurrentUserKey(dwSyncType,KEY_READ,FALSE))
|
|
{
|
|
HKEY hkeyConnectionName;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkeySyncType,pConnectionName,0,KEY_READ,&hkeyConnectionName))
|
|
{
|
|
HKEY hkeyClsid;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkeyConnectionName,pszClsid,0,KEY_READ,&hkeyClsid))
|
|
{
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD fQueryResult;
|
|
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyClsid,TEXT("ItemsChecked"),NULL, &dwType, (LPBYTE) &fQueryResult, &dwDataSize))
|
|
{
|
|
fLoadHandler = fQueryResult;
|
|
}
|
|
|
|
RegCloseKey(hkeyClsid);
|
|
}
|
|
|
|
RegCloseKey(hkeyConnectionName);
|
|
}
|
|
|
|
RegCloseKey(hkeySyncType);
|
|
}
|
|
|
|
|
|
return fLoadHandler;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegSetSyncHandlerSettings( )
|
|
|
|
Summary: Sets the handler settings for syncType and Connection.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegSetSyncHandlerSettings(DWORD dwSyncType,
|
|
const TCHAR *pszConnectionName,
|
|
CLSID clsidHandler,
|
|
BOOL fItemsChecked)
|
|
{
|
|
HKEY hKeyUser;
|
|
|
|
hKeyUser = RegGetCurrentUserKey(dwSyncType,KEY_WRITE | KEY_READ,TRUE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
SCODE sc;
|
|
HKEY hkeyConnection;
|
|
HKEY hkeyCLSID;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
|
|
TCHAR szCLSID[(GUID_SIZE+1)];
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
smChkTo(EH_Err2,RegCreateUserSubKey(hKeyUser,
|
|
pszConnectionName,
|
|
KEY_WRITE | KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
|
|
StringFromGUID2(clsidHandler, szCLSID, 2*GUID_SIZE);
|
|
|
|
// Write entries under CLSID.
|
|
smChkTo(EH_Err3,RegCreateUserSubKey(hkeyConnection,
|
|
szCLSID,KEY_WRITE | KEY_READ,
|
|
&hkeyCLSID));
|
|
|
|
RegSetValueEx(hkeyCLSID,TEXT("ItemsChecked"),NULL, REG_DWORD,
|
|
(LPBYTE) &fItemsChecked,
|
|
sizeof(DWORD));
|
|
|
|
RegCloseKey(hKeyUser);
|
|
RegCloseKey(hkeyConnection);
|
|
RegCloseKey(hkeyCLSID);
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
EH_Err3:
|
|
RegCloseKey(hkeyConnection);
|
|
EH_Err2:
|
|
RegCloseKey(hKeyUser);
|
|
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegLookupSettings(const TCHAR *hkeyName,
|
|
CLSID clsidHandler,
|
|
SYNCMGRITEMID ItemID,
|
|
const TCHAR *pszMachineName,
|
|
const TCHAR *pszConnectionName,
|
|
DWORD pdwCheckState)
|
|
|
|
Summary: Gets the settings per handler, itemID, and connection name.
|
|
|
|
Returns: Returns TRUE if there are settings for this item and
|
|
connection, flase otherwise.
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegLookupSettings(HKEY hKeyUser,
|
|
CLSID clsidHandler,
|
|
SYNCMGRITEMID ItemID,
|
|
const TCHAR *pszConnectionName,
|
|
DWORD *pdwCheckState)
|
|
{
|
|
SCODE sc;
|
|
HKEY hkeyConnection;
|
|
HKEY hkeyItem;
|
|
HKEY hKeyHandler;
|
|
DWORD dwType = REG_SZ;
|
|
DWORD dwDataSize = MAX_PATH + 1;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
TCHAR szID[GUID_SIZE+1];
|
|
TCHAR szCLSID[2*(GUID_SIZE+1)];
|
|
|
|
|
|
dwType = REG_DWORD;
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
smChkTo(EH_Err2,RegOpenKeyEx(hKeyUser,
|
|
pszConnectionName,0,KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
|
|
StringFromGUID2(clsidHandler, szCLSID, 2*GUID_SIZE);
|
|
StringFromGUID2(ItemID, szID, GUID_SIZE);
|
|
|
|
// Read entries under CLSID.
|
|
smChkTo(EH_Err3,RegOpenKeyEx((hkeyConnection),
|
|
szCLSID, 0, KEY_READ,
|
|
&hKeyHandler));
|
|
|
|
smChkTo(EH_Err4,RegOpenKeyEx((hKeyHandler),
|
|
szID, 0, KEY_READ,
|
|
&hkeyItem));
|
|
|
|
RegQueryValueEx(hkeyItem,TEXT("CheckState"),NULL, &dwType, (LPBYTE)pdwCheckState, &dwDataSize);
|
|
|
|
RegCloseKey(hkeyConnection);
|
|
RegCloseKey(hkeyItem);
|
|
RegCloseKey(hKeyHandler);
|
|
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
EH_Err4:
|
|
RegCloseKey(hKeyHandler);
|
|
EH_Err3:
|
|
RegCloseKey(hkeyConnection);
|
|
EH_Err2:
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegWriteOutSettings(const TCHAR *hkeyName,
|
|
CLSID clsidHandler,
|
|
SYNCMGRITEMID ItemID,
|
|
const TCHAR *pszConnectionName,
|
|
DWORD dwCheckState)
|
|
|
|
Summary: Sets the settings per handler, itemID, and connection name.
|
|
|
|
Returns: Returns TRUE if we can set them, FALSE if there is an error
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegWriteOutSettings(HKEY hKeyUser,
|
|
CLSID clsidHandler,
|
|
SYNCMGRITEMID ItemID,
|
|
const TCHAR *pszConnectionName,
|
|
DWORD dwCheckState)
|
|
{
|
|
SCODE sc;
|
|
HKEY hkeyConnection;
|
|
HKEY hKeyHandler;
|
|
HKEY hkeyItem;
|
|
DWORD dwType = REG_SZ;
|
|
DWORD dwDataSize = MAX_PATH;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
TCHAR szID[GUID_SIZE+1];
|
|
TCHAR szCLSID[2*(GUID_SIZE+1)];
|
|
|
|
smChkTo(EH_Err2,RegCreateUserSubKey(hKeyUser,
|
|
pszConnectionName,KEY_WRITE | KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
|
|
StringFromGUID2(clsidHandler, szCLSID, 2*GUID_SIZE);
|
|
StringFromGUID2(ItemID, szID, GUID_SIZE);
|
|
|
|
|
|
smChkTo(EH_Err3,RegCreateUserSubKey(hkeyConnection,
|
|
szCLSID,KEY_WRITE | KEY_READ,
|
|
&hKeyHandler));
|
|
|
|
|
|
// Write entries under CLSID.
|
|
smChkTo(EH_Err4,RegCreateUserSubKey(hKeyHandler,
|
|
szID,KEY_WRITE | KEY_READ,
|
|
&hkeyItem));
|
|
|
|
|
|
RegSetValueEx(hkeyItem,TEXT("CheckState"),NULL, REG_DWORD,
|
|
(LPBYTE) &dwCheckState,
|
|
sizeof(DWORD));
|
|
|
|
RegCloseKey(hkeyConnection);
|
|
RegCloseKey(hkeyItem);
|
|
RegCloseKey(hKeyHandler);
|
|
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
EH_Err4:
|
|
RegCloseKey(hKeyHandler);
|
|
EH_Err3:
|
|
RegCloseKey(hkeyConnection);
|
|
EH_Err2:
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
AutoSync Registry Functions
|
|
|
|
***************************************************************************F-F*/
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegGetAutoSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings)
|
|
|
|
Summary: Gets the logon, logoff and prompt me first user selections.
|
|
If no selections on this connection, the default is ?
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegGetAutoSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings)
|
|
{
|
|
SCODE sc;
|
|
HKEY hkeyConnection;
|
|
DWORD dwType = REG_SZ ;
|
|
DWORD dwDataSize = MAX_PATH;
|
|
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
|
|
// Set these first to default values, in case there are no current
|
|
// user preferences in the registry
|
|
lpConnectionSettings->dwLogon = FALSE;
|
|
lpConnectionSettings->dwLogoff = FALSE;
|
|
lpConnectionSettings->dwPromptMeFirst = FALSE;
|
|
|
|
HKEY hKeyUser;
|
|
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_AUTOSYNC,KEY_READ,FALSE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err;
|
|
}
|
|
|
|
dwType = REG_DWORD ;
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
smChkTo(EH_Err3,RegOpenKeyEx(hKeyUser, lpConnectionSettings->pszConnectionName,0,KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
RegQueryValueEx(hkeyConnection,TEXT("Logon"),NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwLogon),
|
|
&dwDataSize);
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
RegQueryValueEx(hkeyConnection,TEXT("Logoff"),NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwLogoff),
|
|
&dwDataSize);
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
RegQueryValueEx(hkeyConnection,TEXT("PromptMeFirst"),NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwPromptMeFirst),
|
|
&dwDataSize);
|
|
|
|
RegCloseKey(hkeyConnection);
|
|
RegCloseKey(hKeyUser);
|
|
|
|
CMutexRegistry.Leave();
|
|
|
|
return TRUE;
|
|
|
|
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err:
|
|
CMutexRegistry.Leave();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegUpdateUserAutosyncKey
|
|
|
|
Summary: given an Autosync User Key makes sure it is in the latest
|
|
format and if not updates it.
|
|
|
|
Returns:
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
void RegUpdateUserAutosyncKey(HKEY hkeyUser,BOOL fForce)
|
|
{
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD dwUserLogonLogoff;
|
|
DWORD dwIndex = 0;
|
|
TCHAR lpName[MAX_PATH];
|
|
DWORD cbName = MAX_PATH;
|
|
|
|
DWORD dwLogon = 0;
|
|
DWORD dwLogoff = 0;
|
|
|
|
if (!fForce && (ERROR_SUCCESS == RegQueryValueEx(hkeyUser,TEXT("Logon"),NULL, &dwType,
|
|
(LPBYTE) &dwUserLogonLogoff,
|
|
&dwDataSize)) )
|
|
{
|
|
// if can open Logon Key this is up to date.
|
|
return;
|
|
}
|
|
|
|
// need to enum connection names and update the toplevel information.
|
|
while ( ERROR_SUCCESS == RegEnumKey(hkeyUser,dwIndex,
|
|
lpName,cbName) )
|
|
{
|
|
LONG lRet;
|
|
HKEY hKeyConnection;
|
|
|
|
lRet = RegOpenKeyEx( hkeyUser,
|
|
lpName,
|
|
NULL,
|
|
KEY_READ,
|
|
&hKeyConnection );
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKeyConnection,TEXT("Logon"),NULL, &dwType,
|
|
(LPBYTE) &dwUserLogonLogoff,
|
|
&dwDataSize) )
|
|
{
|
|
dwLogon |= dwUserLogonLogoff;
|
|
}
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKeyConnection,TEXT("Logoff"),NULL, &dwType,
|
|
(LPBYTE) &dwUserLogonLogoff,
|
|
&dwDataSize) )
|
|
{
|
|
dwLogoff |= dwUserLogonLogoff;
|
|
}
|
|
|
|
RegCloseKey(hKeyConnection);
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
// write out new flags even if errors occured. work thing that happens is
|
|
// we don't set up someones autosync automatically.
|
|
RegSetValueEx(hkeyUser,TEXT("Logon"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwLogon), sizeof(DWORD));
|
|
RegSetValueEx(hkeyUser,TEXT("Logoff"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwLogoff), sizeof(DWORD));
|
|
|
|
RegWriteTimeStamp(hkeyUser);
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegUpdateAutoSyncKeyValueSettings
|
|
|
|
Summary: walks through the UserList Updating the AutoSync
|
|
|
|
Returns:
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
void RegUpdateAutoSyncKeyValue(HKEY hkeyAutoSync,DWORD dwLogonDefault,DWORD dwLogoffDefault)
|
|
{
|
|
DWORD dwIndex = 0;
|
|
WCHAR lpName[MAX_PATH];
|
|
DWORD cbName = MAX_PATH;
|
|
LONG lRet;
|
|
DWORD dwLogon = 0;
|
|
DWORD dwLogoff = 0;
|
|
BOOL fSetLogon,fSetLogoff;
|
|
|
|
// need to walk the autosync user key and set the top level information
|
|
// based on whther someone logon/logoff
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
while ( ERROR_SUCCESS == (lRet = RegEnumKey(hkeyAutoSync,dwIndex,
|
|
lpName,cbName) ))
|
|
{
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD dwUserLogonLogoff;
|
|
HKEY hKeyDomainUser;
|
|
|
|
lRet = RegOpenKeyEx( hkeyAutoSync,
|
|
lpName,
|
|
NULL,
|
|
KEY_READ,
|
|
&hKeyDomainUser );
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
|
|
// If Query fails don't want to count this as a failed to enum
|
|
// error so don't set lRet
|
|
if (ERROR_SUCCESS == (RegQueryValueEx(hKeyDomainUser,TEXT("Logon"),NULL, &dwType,
|
|
(LPBYTE) &dwUserLogonLogoff,
|
|
&dwDataSize) ))
|
|
{
|
|
dwLogon |= dwUserLogonLogoff;
|
|
}
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
if (ERROR_SUCCESS == (RegQueryValueEx(hKeyDomainUser,TEXT("Logoff"),NULL, &dwType,
|
|
(LPBYTE) &dwUserLogonLogoff,
|
|
&dwDataSize) ) )
|
|
{
|
|
dwLogoff |= dwUserLogonLogoff;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKeyDomainUser);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
fSetLogon = FALSE;
|
|
fSetLogoff = FALSE;
|
|
|
|
// if an error occured, then use the passed in defaults,
|
|
// if set to 1, else don't set.
|
|
if ( (ERROR_SUCCESS != lRet) && (ERROR_NO_MORE_ITEMS != lRet))
|
|
{
|
|
if ( (-1 != dwLogonDefault) && (0 != dwLogonDefault))
|
|
{
|
|
fSetLogon = TRUE;
|
|
dwLogon = dwLogonDefault;
|
|
}
|
|
|
|
if ( (-1 != dwLogoffDefault) && (0 != dwLogoffDefault))
|
|
{
|
|
fSetLogoff = TRUE;
|
|
dwLogoff = dwLogoffDefault;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
fSetLogon = TRUE;
|
|
fSetLogoff = TRUE;
|
|
}
|
|
|
|
// write out new flags even if errors occured. work thing that happens is
|
|
// we don't set up someones autosync automatically.
|
|
|
|
if (fSetLogon)
|
|
{
|
|
RegSetValueEx(hkeyAutoSync,TEXT("Logon"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwLogon), sizeof(DWORD));
|
|
}
|
|
|
|
if (fSetLogoff)
|
|
{
|
|
RegSetValueEx(hkeyAutoSync,TEXT("Logoff"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwLogoff), sizeof(DWORD));
|
|
}
|
|
|
|
RegWriteTimeStamp(hkeyAutoSync);
|
|
|
|
CMutexRegistry.Leave();
|
|
}
|
|
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegUpdateUserIdleKey
|
|
|
|
Summary: given an Idle User Key makes sure it is in the latest
|
|
format and if not updates it.
|
|
|
|
Returns:
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
void RegUpdateUserIdleKey(HKEY hkeyUser,BOOL fForce)
|
|
{
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD dwUserIdleEnabled;
|
|
DWORD dwIndex = 0;
|
|
TCHAR lpName[MAX_PATH];
|
|
DWORD cbName = MAX_PATH;
|
|
|
|
DWORD dwIdleEnabled = 0;
|
|
|
|
if (!fForce && (ERROR_SUCCESS == RegQueryValueEx(hkeyUser,TEXT("IdleEnabled"),NULL, &dwType,
|
|
(LPBYTE) &dwUserIdleEnabled,
|
|
&dwDataSize)) )
|
|
{
|
|
// if can open Logon Key this is up to date.
|
|
return;
|
|
}
|
|
|
|
// need to enum connection names and update the toplevel information.
|
|
while ( ERROR_SUCCESS == RegEnumKey(hkeyUser,dwIndex,
|
|
lpName,cbName) )
|
|
{
|
|
LONG lRet;
|
|
HKEY hKeyConnection;
|
|
|
|
lRet = RegOpenKeyEx( hkeyUser,
|
|
lpName,
|
|
NULL,
|
|
KEY_READ,
|
|
&hKeyConnection );
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKeyConnection,TEXT("IdleEnabled"),NULL, &dwType,
|
|
(LPBYTE) &dwUserIdleEnabled,
|
|
&dwDataSize) )
|
|
{
|
|
dwIdleEnabled |= dwUserIdleEnabled;
|
|
}
|
|
|
|
RegCloseKey(hKeyConnection);
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
// write out new flags even if errors occured. work thing that happens is
|
|
// we don't set up someones autosync automatically.
|
|
RegSetValueEx(hkeyUser,TEXT("IdleEnabled"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwIdleEnabled), sizeof(DWORD));
|
|
RegWriteTimeStamp(hkeyUser);
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegUpdateIdleKeyValue
|
|
|
|
Summary: walks through the UserList Updating the Idle RegKey
|
|
|
|
Returns:
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
void RegUpdateIdleKeyValue(HKEY hkeyIdle,DWORD dwDefault)
|
|
{
|
|
DWORD dwIndex = 0;
|
|
WCHAR lpName[MAX_PATH];
|
|
DWORD cbName = MAX_PATH;
|
|
DWORD dwIdleEnabled = 0;
|
|
LONG lRet = -1;
|
|
BOOL fSetDefault;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
// need to walk the idle user key and set the top level information
|
|
// based on whther someone logon/logoff
|
|
|
|
fSetDefault = FALSE;
|
|
|
|
|
|
while ( ERROR_SUCCESS == (lRet = RegEnumKey(hkeyIdle,dwIndex,
|
|
lpName,cbName)) )
|
|
{
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD dwUserIdleEnabled;
|
|
HKEY hKeyDomainUser;
|
|
|
|
lRet = RegOpenKeyEx( hkeyIdle,
|
|
lpName,
|
|
NULL,
|
|
KEY_READ,
|
|
&hKeyDomainUser );
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
|
|
// if query fails don't consider this an error as far as
|
|
// setDefault goes.
|
|
if (ERROR_SUCCESS == (RegQueryValueEx(hKeyDomainUser,TEXT("IdleEnabled"),NULL, &dwType,
|
|
(LPBYTE) &dwUserIdleEnabled,
|
|
&dwDataSize) ))
|
|
{
|
|
dwIdleEnabled |= dwUserIdleEnabled;
|
|
}
|
|
|
|
RegCloseKey(hKeyDomainUser);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
// if an error occured, then use the passed in defaults,
|
|
// if set to 1, else don't set.
|
|
if ( (ERROR_SUCCESS != lRet) && (ERROR_NO_MORE_ITEMS != lRet))
|
|
{
|
|
if ( (-1 != dwDefault) && (0 != dwDefault))
|
|
{
|
|
fSetDefault = TRUE;
|
|
dwIdleEnabled = dwDefault;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
fSetDefault = TRUE;
|
|
}
|
|
|
|
|
|
// write out new flags even if errors occured. work thing that happens is
|
|
// we don't set up someones autosync automatically.
|
|
|
|
if (fSetDefault)
|
|
{
|
|
RegSetValueEx(hkeyIdle,TEXT("IdleEnabled"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwIdleEnabled), sizeof(DWORD));
|
|
}
|
|
|
|
RegWriteTimeStamp(hkeyIdle);
|
|
CMutexRegistry.Leave();
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegSetAutoSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings,
|
|
int iNumConnections)
|
|
|
|
Summary: Sets the logon, logoff and prompt me first user selections.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegSetAutoSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings,
|
|
int iNumConnections,
|
|
CRasUI *pRas,
|
|
BOOL fCleanReg,
|
|
BOOL fSetMachineState,
|
|
BOOL fPerUser)
|
|
{
|
|
SCODE sc = S_OK;
|
|
HKEY hAutoSync;
|
|
HKEY hKeyUser;
|
|
HKEY hkeyConnection;
|
|
DWORD dwUserConfigured = 1;
|
|
DWORD dwLogonDefault = -1;
|
|
DWORD dwLogoffDefault = -1;
|
|
int i;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
// make sure keys are converted to newest format
|
|
RegUpdateTopLevelKeys();
|
|
|
|
Assert(-1 != TRUE); // we rely on TRUE boolean being something other than -1
|
|
|
|
hAutoSync = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_WRITE| KEY_READ,TRUE);
|
|
|
|
if (NULL == hAutoSync)
|
|
{
|
|
goto EH_Err;
|
|
}
|
|
|
|
hKeyUser = RegOpenUserKey(hAutoSync,KEY_WRITE| KEY_READ,TRUE,fCleanReg);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err2;
|
|
}
|
|
|
|
if (fPerUser)
|
|
{
|
|
|
|
smChkTo(EH_Err3,RegSetValueEx(hKeyUser,TEXT("UserConfigured"),NULL, REG_DWORD,
|
|
(LPBYTE) &dwUserConfigured,
|
|
sizeof(DWORD)));
|
|
}
|
|
else
|
|
{
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
|
|
//If this value isn't added yet,
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKeyUser,TEXT("UserConfigured"),NULL, &dwType,
|
|
(LPBYTE) &dwUserConfigured,
|
|
&dwDataSize))
|
|
{
|
|
//if the user setup their configuration, we won't override on a
|
|
//subsequent handler registration.
|
|
if (dwUserConfigured)
|
|
{
|
|
RegCloseKey(hKeyUser);
|
|
RegCloseKey(hAutoSync);
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i=0; i<iNumConnections; i++)
|
|
{
|
|
|
|
smChkTo(EH_Err3,RegCreateUserSubKey (hKeyUser,
|
|
lpConnectionSettings[i].pszConnectionName,
|
|
KEY_WRITE | KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
|
|
if (-1 != lpConnectionSettings[i].dwLogon)
|
|
{
|
|
|
|
if (0 != lpConnectionSettings[i].dwLogon)
|
|
{
|
|
dwLogonDefault = lpConnectionSettings[i].dwLogon;
|
|
}
|
|
|
|
smChkTo(EH_Err4,RegSetValueEx(hkeyConnection,TEXT("Logon"),NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[i].dwLogon),
|
|
sizeof(DWORD)));
|
|
}
|
|
|
|
if (-1 != lpConnectionSettings[i].dwLogoff)
|
|
{
|
|
|
|
if (0 != lpConnectionSettings[i].dwLogoff)
|
|
{
|
|
dwLogoffDefault = lpConnectionSettings[i].dwLogoff;
|
|
}
|
|
|
|
smChkTo(EH_Err4,RegSetValueEx(hkeyConnection,TEXT("Logoff"),NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[i].dwLogoff),
|
|
sizeof(DWORD)));
|
|
}
|
|
|
|
|
|
if (-1 != lpConnectionSettings[i].dwPromptMeFirst)
|
|
{
|
|
smChkTo(EH_Err4,RegSetValueEx(hkeyConnection,TEXT("PromptMeFirst"),NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[i].dwPromptMeFirst),
|
|
sizeof(DWORD)));
|
|
}
|
|
|
|
RegCloseKey(hkeyConnection);
|
|
|
|
}
|
|
|
|
// update the toplevel User information
|
|
RegUpdateUserAutosyncKey(hKeyUser,TRUE /* fForce */);
|
|
|
|
// update the top-level key
|
|
RegUpdateAutoSyncKeyValue(hAutoSync,dwLogonDefault,dwLogoffDefault);
|
|
|
|
RegCloseKey(hKeyUser);
|
|
RegCloseKey(hAutoSync);
|
|
|
|
// update our global sens state based on Autosync and Registration
|
|
|
|
if (fSetMachineState)
|
|
{
|
|
RegRegisterForEvents(FALSE /* fUninstall */);
|
|
}
|
|
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
EH_Err4:
|
|
RegCloseKey(hkeyConnection);
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err2:
|
|
RegCloseKey(hAutoSync);
|
|
EH_Err:
|
|
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Scheduled Sync Registry Functions
|
|
|
|
***************************************************************************F-F*/
|
|
//--------------------------------------------------------------------------------
|
|
//
|
|
// FUNCTION: RegGetSchedFriendlyName(LPCTSTR ptszScheduleGUIDName,
|
|
// LPTSTR ptstrFriendlyName)
|
|
//
|
|
// PURPOSE: Get the friendly name of this Schedule.
|
|
//
|
|
// History: 27-Feb-98 susia Created.
|
|
//
|
|
//--------------------------------------------------------------------------------
|
|
STDAPI_(BOOL) RegGetSchedFriendlyName(LPCTSTR ptszScheduleGUIDName,
|
|
LPTSTR ptstrFriendlyName)
|
|
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hkeySchedName;
|
|
DWORD dwType = REG_SZ;
|
|
DWORD dwDataSize = (MAX_PATH + 1) * sizeof(TCHAR);
|
|
|
|
HKEY hKeyUser;
|
|
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (NOERROR == RegOpenKeyEx (hKeyUser, ptszScheduleGUIDName, 0,KEY_READ,
|
|
&hkeySchedName))
|
|
{
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeySchedName,TEXT("FriendlyName"),NULL, &dwType,
|
|
(LPBYTE) ptstrFriendlyName, &dwDataSize))
|
|
{
|
|
fResult = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hkeySchedName);
|
|
}
|
|
|
|
|
|
RegCloseKey(hKeyUser);
|
|
return fResult;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
//
|
|
// FUNCTION: RegSetSchedFriendlyName(LPCTSTR ptszScheduleGUIDName,
|
|
// LPCTSTR ptstrFriendlyName)
|
|
//
|
|
// PURPOSE: Set the friendly name of this Schedule.
|
|
//
|
|
// History: 27-Feb-98 susia Created.
|
|
//
|
|
//--------------------------------------------------------------------------------
|
|
STDAPI_(BOOL) RegSetSchedFriendlyName(LPCTSTR ptszScheduleGUIDName,
|
|
LPCTSTR ptstrFriendlyName)
|
|
|
|
{
|
|
SCODE sc;
|
|
HKEY hkeySchedName;
|
|
DWORD dwType = REG_SZ;
|
|
HKEY hKeyUser;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_WRITE | KEY_READ,TRUE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err;
|
|
}
|
|
|
|
smChkTo(EH_Err3,RegCreateUserSubKey (hKeyUser, ptszScheduleGUIDName,
|
|
KEY_WRITE | KEY_READ,
|
|
&hkeySchedName));
|
|
|
|
|
|
smChkTo(EH_Err4,RegSetValueEx (hkeySchedName,TEXT("FriendlyName"),NULL,
|
|
dwType,
|
|
(LPBYTE) ptstrFriendlyName,
|
|
(lstrlen(ptstrFriendlyName) + 1)*sizeof(TCHAR)));
|
|
|
|
RegCloseKey(hkeySchedName);
|
|
RegCloseKey(hKeyUser);
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
EH_Err4:
|
|
RegCloseKey(hkeySchedName);
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err:
|
|
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegGetSchedSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings,
|
|
TCHAR *pszSchedName)
|
|
|
|
Summary: Gets the MakeAutoConnection user selections.
|
|
If no selections on this connection, the default is FALSE
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegGetSchedSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings,
|
|
TCHAR *pszSchedName)
|
|
{
|
|
SCODE sc;
|
|
HKEY hkeySchedName,
|
|
hkeyConnection;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
HKEY hKeyUser;
|
|
|
|
// Set these first to default values, in case there are no current
|
|
// user preferences in the registry
|
|
lpConnectionSettings->dwConnType = SYNCSCHEDINFO_FLAGS_CONNECTION_LAN;
|
|
lpConnectionSettings->dwMakeConnection = FALSE;
|
|
lpConnectionSettings->dwHidden = FALSE;
|
|
lpConnectionSettings->dwReadOnly = FALSE;
|
|
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE);
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err2;
|
|
}
|
|
|
|
|
|
smChkTo(EH_Err3,RegOpenKeyEx (hKeyUser,
|
|
pszSchedName,0,KEY_READ,
|
|
&hkeySchedName));
|
|
|
|
smChkTo(EH_Err4,RegQueryValueEx(hkeySchedName,TEXT("ScheduleHidden"),NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwHidden),
|
|
&dwDataSize));
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
smChkTo(EH_Err4,RegQueryValueEx(hkeySchedName,TEXT("ScheduleReadOnly"),NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwReadOnly),
|
|
&dwDataSize));
|
|
|
|
smChkTo(EH_Err4,RegOpenKeyEx (hkeySchedName,
|
|
lpConnectionSettings->pszConnectionName,
|
|
0,KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
smChkTo(EH_Err5,RegQueryValueEx(hkeyConnection,TEXT("MakeAutoConnection"),NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwMakeConnection),
|
|
&dwDataSize));
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
smChkTo(EH_Err5,RegQueryValueEx(hkeyConnection,TEXT("Connection Type"),NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwConnType),
|
|
&dwDataSize));
|
|
|
|
RegCloseKey(hkeyConnection);
|
|
RegCloseKey(hkeySchedName);
|
|
RegCloseKey(hKeyUser);
|
|
return TRUE;
|
|
|
|
EH_Err5:
|
|
RegCloseKey(hkeyConnection);
|
|
EH_Err4:
|
|
RegCloseKey(hkeySchedName);
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err2:
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegSetSchedSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings,
|
|
TCHAR *pszSchedName)
|
|
|
|
Summary: Sets the hidden and readonly schedule flags.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegSetSchedSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings,
|
|
TCHAR *pszSchedName)
|
|
{
|
|
SCODE sc;
|
|
HKEY hKeyUser,
|
|
hkeySchedName,
|
|
hkeyConnection;
|
|
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ | KEY_WRITE,TRUE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err;
|
|
}
|
|
|
|
smChkTo(EH_Err3,RegCreateUserSubKey (hKeyUser,
|
|
pszSchedName,
|
|
KEY_WRITE | KEY_READ,
|
|
&hkeySchedName));
|
|
|
|
smChkTo(EH_Err4,RegSetValueEx(hkeySchedName,TEXT("ScheduleHidden"),NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings->dwHidden),
|
|
sizeof(DWORD)));
|
|
|
|
smChkTo(EH_Err4,RegSetValueEx(hkeySchedName,TEXT("ScheduleReadOnly"),NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings->dwReadOnly),
|
|
sizeof(DWORD)));
|
|
|
|
smChkTo(EH_Err4,RegCreateUserSubKey ( hkeySchedName,
|
|
lpConnectionSettings->pszConnectionName,
|
|
KEY_WRITE | KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
smChkTo(EH_Err5,RegSetValueEx(hkeyConnection,TEXT("MakeAutoConnection"),NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings->dwMakeConnection),
|
|
sizeof(DWORD)));
|
|
|
|
smChkTo(EH_Err5,RegSetValueEx(hkeyConnection,TEXT("Connection Type"),NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings->dwConnType),
|
|
sizeof(DWORD)));
|
|
|
|
RegCloseKey(hkeyConnection);
|
|
RegCloseKey(hkeySchedName);
|
|
RegCloseKey(hKeyUser);
|
|
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
EH_Err5:
|
|
RegCloseKey(hkeyConnection);
|
|
EH_Err4:
|
|
RegCloseKey(hkeySchedName);
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err:
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegGetSchedConnectionName(TCHAR *pszSchedName,
|
|
TCHAR *pszConnectionName,
|
|
DWORD cbConnectionName)
|
|
|
|
|
|
Summary: returns the Connection Name for the Scheduled Item.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegGetSchedConnectionName(TCHAR *pszSchedName,TCHAR *pszConnectionName,
|
|
DWORD cbConnectionName)
|
|
{
|
|
SCODE sc;
|
|
BOOL fResult = FALSE;
|
|
HKEY hKeyUser,hkeySchedName;
|
|
DWORD dwIndex = 0;
|
|
DWORD cb = cbConnectionName;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
|
|
//First Set the connectionName to a default.
|
|
// for now we always assume a LAN card is present.
|
|
// if add support for connection manager should
|
|
// update this.
|
|
|
|
LoadString(g_hmodThisDll, IDS_LAN_CONNECTION, pszConnectionName, cbConnectionName);
|
|
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err;
|
|
}
|
|
|
|
smChkTo(EH_Err3, RegOpenKeyEx (hKeyUser,pszSchedName,
|
|
0,KEY_READ, &hkeySchedName));
|
|
|
|
// next enumeration of keys is the names of the Schedules connection
|
|
// currently just have one so only get the first.
|
|
if ( ERROR_SUCCESS == (sc = RegEnumKeyEx(hkeySchedName,dwIndex,
|
|
pszConnectionName,&cb,NULL,NULL,NULL,NULL)) )
|
|
{
|
|
fResult = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hkeySchedName);
|
|
RegCloseKey(hKeyUser);
|
|
|
|
return fResult;
|
|
|
|
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err:
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: BOOL RegSetSIDForSchedule( TCHAR *pszSchedName)
|
|
|
|
Summary: sets the SID for this schedule
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegSetSIDForSchedule(TCHAR *pszSchedName)
|
|
|
|
{
|
|
SCODE sc;
|
|
HKEY hkeySchedName;
|
|
TCHAR pszSID[MAX_PATH + 1];
|
|
DWORD dwSize = MAX_PATH;
|
|
DWORD dwType = REG_SZ;
|
|
|
|
|
|
if (!GetUserTextualSid(pszSID, &dwSize))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
HKEY hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ | KEY_WRITE,TRUE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err2;
|
|
}
|
|
|
|
smChkTo(EH_Err3,RegCreateUserSubKey (hKeyUser, pszSchedName,
|
|
KEY_WRITE | KEY_READ,
|
|
&hkeySchedName));
|
|
|
|
|
|
smChkTo(EH_Err4,RegSetValueEx (hkeySchedName,TEXT("SID"),NULL,
|
|
dwType,
|
|
(LPBYTE) pszSID,
|
|
(lstrlen(pszSID) + 1)*sizeof(TCHAR)));
|
|
|
|
RegCloseKey(hkeySchedName);
|
|
RegCloseKey(hKeyUser);
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
EH_Err4:
|
|
RegCloseKey(hkeySchedName);
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err2:
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: BOOL RegGetSIDForSchedule( TCHAR *ptszTextualSidSched,
|
|
DWORD *dwSizeSid, TCHAR *pszSchedName)
|
|
|
|
Summary: returns the SID for this schedule
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegGetSIDForSchedule(TCHAR *ptszTextualSidSched, DWORD *pdwSizeSid, TCHAR *pszSchedName)
|
|
{
|
|
SCODE sc;
|
|
HKEY hkeySchedName;
|
|
DWORD dwIndex = 0;
|
|
DWORD dwType = REG_SZ;
|
|
DWORD dwSizeSidSave = *pdwSizeSid,
|
|
dwSizeSidSave2 = *pdwSizeSid;
|
|
DWORD dwTouched = TRUE;
|
|
|
|
ptszTextualSidSched[0] = TEXT('\0');
|
|
*pdwSizeSid = 0;
|
|
|
|
HKEY hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err2;
|
|
}
|
|
|
|
smChkTo(EH_Err3, RegOpenKeyEx (hKeyUser,pszSchedName,
|
|
0,KEY_READ, &hkeySchedName));
|
|
|
|
|
|
if (ERROR_SUCCESS != (sc = RegQueryValueEx(hkeySchedName,TEXT("SID"),NULL, &dwType,
|
|
(LPBYTE) ptszTextualSidSched, &dwSizeSidSave)))
|
|
{
|
|
//handle migration from schedules without SIDs
|
|
// like from Beta to current builds
|
|
RegSetSIDForSchedule(pszSchedName);
|
|
|
|
RegQueryValueEx(hkeySchedName,TEXT("SID"),NULL, &dwType,
|
|
(LPBYTE) ptszTextualSidSched, &dwSizeSidSave2);
|
|
|
|
*pdwSizeSid = dwSizeSidSave2;
|
|
}
|
|
else
|
|
{
|
|
*pdwSizeSid = dwSizeSidSave;
|
|
}
|
|
|
|
RegCloseKey(hkeySchedName);
|
|
RegCloseKey(hKeyUser);
|
|
return TRUE;
|
|
|
|
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err2:
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
BOOL RemoveScheduledJobFile(TCHAR *pszTaskName)
|
|
|
|
Summary: Remove the TaskScheduler .job file
|
|
|
|
Note: Try to use ITask->Delete first
|
|
Call only when TaskScheduler isn't present or if ITask->Delete failed
|
|
|
|
Returns: Returns TRUE always
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RemoveScheduledJobFile(TCHAR *pszTaskName)
|
|
{
|
|
SCODE sc;
|
|
TCHAR pszFullFileName[MAX_PATH+1];
|
|
TCHAR pszTaskFolderPath[MAX_PATH+1];
|
|
HKEY hkeyTaskSchedulerPath;
|
|
DWORD dwType = REG_SZ;
|
|
DWORD dwDataSize = MAX_PATH * sizeof(TCHAR);
|
|
|
|
|
|
if (ERROR_SUCCESS == (sc = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
TEXT("SOFTWARE\\Microsoft\\SchedulingAgent"),
|
|
NULL,KEY_READ,&hkeyTaskSchedulerPath)))
|
|
{
|
|
|
|
sc = RegQueryValueEx(hkeyTaskSchedulerPath,TEXT("TasksFolder"),
|
|
NULL, &dwType,
|
|
(LPBYTE) pszTaskFolderPath, &dwDataSize);
|
|
RegCloseKey(hkeyTaskSchedulerPath);
|
|
}
|
|
|
|
//If this get doesn't exist then bail.
|
|
if (ERROR_SUCCESS != sc)
|
|
{
|
|
return FALSE;
|
|
}
|
|
ExpandEnvironmentStrings(pszTaskFolderPath,pszFullFileName,MAX_PATH);
|
|
wcscat(pszFullFileName, L"\\");
|
|
wcscat(pszFullFileName,pszTaskName);
|
|
|
|
//if we fail this, ignore the error. We tried, there isn't much else we can do.
|
|
//So we have a turd file.
|
|
sc = DeleteFile(pszFullFileName);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
BOOL RegRemoveScheduledTask(TCHAR *pszTaskName)
|
|
|
|
Summary: Remove the Scheduled task info from the registry.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegRemoveScheduledTask(TCHAR *pszTaskName)
|
|
{
|
|
HKEY hKeyUser;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ | KEY_WRITE,FALSE);
|
|
|
|
if (hKeyUser)
|
|
{
|
|
RegDeleteKeyNT(hKeyUser, pszTaskName);
|
|
RegCloseKey(hKeyUser);
|
|
}
|
|
|
|
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
BOOL RegUninstallSchedules()
|
|
|
|
Summary: Uninstall the scheduled tasks.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegUninstallSchedules()
|
|
{
|
|
SCODE sc;
|
|
ITaskScheduler *pITaskScheduler = NULL;
|
|
HKEY hkeySchedSync;
|
|
|
|
// Obtain a task scheduler class instance.
|
|
sc = CoCreateInstance(
|
|
CLSID_CTaskScheduler,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ITaskScheduler,
|
|
(VOID **)&pITaskScheduler);
|
|
|
|
if (NOERROR != sc)
|
|
{
|
|
pITaskScheduler = NULL;
|
|
}
|
|
|
|
//now go through and delete the schedules
|
|
|
|
hkeySchedSync = RegGetSyncTypeKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE);
|
|
|
|
if (hkeySchedSync)
|
|
{
|
|
int iUserCount = 0;
|
|
|
|
while (sc == ERROR_SUCCESS )
|
|
{
|
|
HKEY hkeyDomainUser;
|
|
TCHAR szDomainUser[MAX_KEY_LENGTH];
|
|
SCODE sc2;
|
|
DWORD dwDataSize;
|
|
|
|
|
|
dwDataSize = MAX_KEY_LENGTH;
|
|
sc = RegEnumKeyEx(hkeySchedSync,iUserCount,szDomainUser,&dwDataSize,NULL,NULL,NULL,NULL);
|
|
iUserCount++;
|
|
|
|
if(sc == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
sc2 = RegOpenKeyEx (hkeySchedSync,szDomainUser,0,KEY_READ, &hkeyDomainUser);
|
|
|
|
if (ERROR_SUCCESS == sc2)
|
|
{
|
|
int iScheduleCount = 0;
|
|
|
|
while (sc2 == ERROR_SUCCESS )
|
|
{
|
|
TCHAR ptszScheduleGUIDName[MAX_KEY_LENGTH];
|
|
//Add 4 to ensure that we can hold the .job extension if necessary
|
|
WCHAR pwszScheduleGUIDName[MAX_SCHEDULENAMESIZE + 4];
|
|
|
|
dwDataSize = MAX_KEY_LENGTH;
|
|
sc2 = RegEnumKeyEx(hkeyDomainUser,iScheduleCount,ptszScheduleGUIDName,&dwDataSize,NULL,NULL,NULL,NULL);
|
|
|
|
iScheduleCount++;
|
|
|
|
if(sc2 == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
ConvertString(pwszScheduleGUIDName,ptszScheduleGUIDName,MAX_SCHEDULENAMESIZE);
|
|
|
|
if ((!pITaskScheduler) ||
|
|
FAILED(pITaskScheduler->Delete(pwszScheduleGUIDName)))
|
|
{
|
|
wcscat(pwszScheduleGUIDName, L".job");
|
|
RemoveScheduledJobFile(pwszScheduleGUIDName);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyDomainUser);
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey(hkeySchedSync);
|
|
}
|
|
|
|
if (pITaskScheduler)
|
|
{
|
|
pITaskScheduler->Release();
|
|
}
|
|
|
|
RegDeleteKeyNT(HKEY_LOCAL_MACHINE, SCHEDSYNC_REGKEY);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Idle Registry Functions
|
|
|
|
***************************************************************************F-F*/
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegGetIdleSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings)
|
|
|
|
Summary: Gets the Idle Specific settings.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegGetIdleSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings)
|
|
{
|
|
SCODE sc;
|
|
HKEY hkeyConnection;
|
|
DWORD dwType = REG_SZ ;
|
|
DWORD dwDataSize = MAX_PATH;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
// set up defaults
|
|
|
|
lpConnectionSettings->dwIdleEnabled = 0;
|
|
|
|
// following are really per user not per connection
|
|
lpConnectionSettings->ulIdleWaitMinutes = UL_DEFAULTIDLEWAITMINUTES;
|
|
lpConnectionSettings->ulIdleRetryMinutes = UL_DEFAULTIDLERETRYMINUTES;
|
|
lpConnectionSettings->ulDelayIdleShutDownTime = UL_DELAYIDLESHUTDOWNTIME;
|
|
lpConnectionSettings->dwRepeatSynchronization = UL_DEFAULTREPEATSYNCHRONIZATION;
|
|
lpConnectionSettings->dwRunOnBatteries = UL_DEFAULTFRUNONBATTERIES;
|
|
|
|
HKEY hKeyUser = RegGetCurrentUserKey(SYNCTYPE_IDLE,KEY_READ,FALSE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err2;
|
|
}
|
|
|
|
|
|
dwType = REG_DWORD ;
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
// if got the Idle key open then fill in global settings
|
|
|
|
RegQueryValueEx(hKeyUser,SZ_IDLEWAITAFTERIDLEMINUTESKEY,NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->ulIdleWaitMinutes),
|
|
&dwDataSize);
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
RegQueryValueEx(hKeyUser,SZ_IDLEREPEATESYNCHRONIZATIONKEY,NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwRepeatSynchronization),
|
|
&dwDataSize);
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
RegQueryValueEx(hKeyUser,SZ_IDLERETRYMINUTESKEY,NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->ulIdleRetryMinutes),
|
|
&dwDataSize);
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
RegQueryValueEx(hKeyUser,SZ_IDLEDELAYSHUTDOWNTIMEKEY,NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->ulDelayIdleShutDownTime),
|
|
&dwDataSize);
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
RegQueryValueEx(hKeyUser,SZ_IDLERUNONBATTERIESKEY,NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwRunOnBatteries),
|
|
&dwDataSize);
|
|
|
|
smChkTo(EH_Err3,RegOpenKeyEx(hKeyUser, lpConnectionSettings->pszConnectionName,0,KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
RegQueryValueEx(hkeyConnection,TEXT("IdleEnabled"),NULL, &dwType,
|
|
(LPBYTE) &(lpConnectionSettings->dwIdleEnabled),
|
|
&dwDataSize);
|
|
|
|
RegCloseKey(hkeyConnection);
|
|
RegCloseKey(hKeyUser);
|
|
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err2:
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegSetIdleSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings,
|
|
int iNumConnections,
|
|
CRasUI *pRas,
|
|
BOOL fCleanReg,
|
|
BOOL fPerUser)
|
|
|
|
Summary: Sets the Idle Information user selections.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
STDAPI_(BOOL) RegSetIdleSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings,
|
|
int iNumConnections,
|
|
CRasUI *pRas,
|
|
BOOL fCleanReg,
|
|
BOOL fPerUser)
|
|
{
|
|
HKEY hkeyIdleSync = NULL;
|
|
HKEY hKeyUser;;
|
|
HKEY hkeyConnection;
|
|
HRESULT hr;
|
|
ULONG ulWaitMinutes = UL_DEFAULTWAITMINUTES;
|
|
DWORD dwIdleEnabled;
|
|
BOOL fRunOnBatteries = UL_DEFAULTFRUNONBATTERIES;
|
|
int i;
|
|
DWORD dwType;
|
|
DWORD dwDataSize;
|
|
DWORD dwUserConfigured;
|
|
DWORD dwTopLevelDefaultValue = -1;
|
|
|
|
RegUpdateTopLevelKeys(); // make sure top-level keys are latest version
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
Assert(-1 != TRUE); // we rely on TRUE boolean being something other than -1
|
|
|
|
hkeyIdleSync = RegGetSyncTypeKey(SYNCTYPE_IDLE,KEY_WRITE| KEY_READ,TRUE);
|
|
|
|
if (NULL == hkeyIdleSync)
|
|
{
|
|
goto EH_Err;
|
|
}
|
|
|
|
hKeyUser = RegOpenUserKey(hkeyIdleSync,KEY_WRITE| KEY_READ,TRUE,fCleanReg);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
goto EH_Err2;
|
|
}
|
|
|
|
|
|
if (fPerUser)
|
|
{
|
|
|
|
dwUserConfigured = 1;
|
|
|
|
if (ERROR_SUCCESS != RegSetValueEx(hKeyUser,TEXT("UserConfigured"),NULL, REG_DWORD,
|
|
(LPBYTE) &dwUserConfigured,
|
|
sizeof(DWORD)))
|
|
{
|
|
goto EH_Err3;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwType = REG_DWORD;
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
//If this value isn't added yet,
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKeyUser,TEXT("UserConfigured"),NULL, &dwType,
|
|
(LPBYTE) &dwUserConfigured,
|
|
&dwDataSize))
|
|
{
|
|
//if the user setup their configuration, we won't override on a
|
|
//subsequent handler registration.
|
|
if (dwUserConfigured)
|
|
{
|
|
RegCloseKey(hkeyIdleSync);
|
|
RegCloseKey(hKeyUser);
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i=0; i<iNumConnections; i++)
|
|
{
|
|
|
|
if (ERROR_SUCCESS != RegCreateUserSubKey (hKeyUser,
|
|
lpConnectionSettings[i].pszConnectionName,
|
|
KEY_WRITE | KEY_READ,
|
|
&hkeyConnection))
|
|
{
|
|
goto EH_Err3;
|
|
}
|
|
|
|
|
|
hr = RegSetValueEx(hkeyConnection,TEXT("IdleEnabled"),NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[i].dwIdleEnabled),
|
|
sizeof(DWORD));
|
|
|
|
if (lpConnectionSettings[i].dwIdleEnabled)
|
|
{
|
|
dwTopLevelDefaultValue = lpConnectionSettings[i].dwIdleEnabled;
|
|
}
|
|
|
|
RegCloseKey(hkeyConnection);
|
|
|
|
}
|
|
// write out the global idle information for Retry minutes and DelayIdleShutDown.
|
|
// then call function to reg/unregister with TS.
|
|
|
|
|
|
Assert(hkeyIdleSync); // should have already returned if this failed.
|
|
|
|
if (iNumConnections) // make sure at least one connection
|
|
{
|
|
|
|
// ONLY UPDATE SETTINGS IF NOT -1;
|
|
|
|
if (-1 != lpConnectionSettings[0].ulIdleRetryMinutes)
|
|
{
|
|
hr = RegSetValueEx(hKeyUser,SZ_IDLERETRYMINUTESKEY,NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[0].ulIdleRetryMinutes),
|
|
sizeof(DWORD));
|
|
}
|
|
|
|
if (-1 != lpConnectionSettings[0].ulDelayIdleShutDownTime)
|
|
{
|
|
hr = RegSetValueEx(hKeyUser,SZ_IDLEDELAYSHUTDOWNTIMEKEY,NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[0].ulDelayIdleShutDownTime),
|
|
sizeof(DWORD));
|
|
}
|
|
|
|
if (-1 != lpConnectionSettings[0].dwRepeatSynchronization)
|
|
{
|
|
hr = RegSetValueEx(hKeyUser,SZ_IDLEREPEATESYNCHRONIZATIONKEY,NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[0].dwRepeatSynchronization),
|
|
sizeof(DWORD));
|
|
}
|
|
|
|
|
|
|
|
if (-1 != lpConnectionSettings[0].ulIdleWaitMinutes)
|
|
{
|
|
hr = RegSetValueEx(hKeyUser,SZ_IDLEWAITAFTERIDLEMINUTESKEY,NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[0].ulIdleWaitMinutes),
|
|
sizeof(DWORD));
|
|
}
|
|
|
|
|
|
if (-1 != lpConnectionSettings[0].dwRunOnBatteries)
|
|
{
|
|
hr = RegSetValueEx(hKeyUser,SZ_IDLERUNONBATTERIESKEY,NULL, REG_DWORD,
|
|
(LPBYTE) &(lpConnectionSettings[0].dwRunOnBatteries),
|
|
sizeof(DWORD));
|
|
}
|
|
|
|
ulWaitMinutes = lpConnectionSettings[0].ulIdleWaitMinutes;
|
|
fRunOnBatteries = lpConnectionSettings[0].dwRunOnBatteries;
|
|
|
|
// if -1 is passed in for ulWait or fRun on Batteries we need to
|
|
// get these and set them up so they can be passed onto Task Schedule
|
|
if (-1 == ulWaitMinutes)
|
|
{
|
|
dwType = REG_DWORD ;
|
|
dwDataSize = sizeof(ulWaitMinutes);
|
|
|
|
if (!(ERROR_SUCCESS == RegQueryValueEx(hKeyUser,SZ_IDLEWAITAFTERIDLEMINUTESKEY,NULL, &dwType,
|
|
(LPBYTE) &ulWaitMinutes,
|
|
&dwDataSize)) )
|
|
{
|
|
ulWaitMinutes = UL_DEFAULTIDLEWAITMINUTES;
|
|
}
|
|
}
|
|
|
|
if (-1 == fRunOnBatteries)
|
|
{
|
|
dwType = REG_DWORD ;
|
|
dwDataSize = sizeof(fRunOnBatteries);
|
|
|
|
if (!(ERROR_SUCCESS == RegQueryValueEx(hKeyUser,SZ_IDLERUNONBATTERIESKEY,NULL, &dwType,
|
|
(LPBYTE) &fRunOnBatteries,
|
|
&dwDataSize)) )
|
|
{
|
|
fRunOnBatteries = UL_DEFAULTFRUNONBATTERIES;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
RegUpdateUserIdleKey(hKeyUser,TRUE /* fForce */); // set userlevel IdleFlags
|
|
|
|
// read in dwIdleEnabled key now that the UserKey is Updated.
|
|
dwType = REG_DWORD ;
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
if (!(ERROR_SUCCESS == RegQueryValueEx(hKeyUser,TEXT("IdleEnabled"),NULL, &dwType,
|
|
(LPBYTE) &dwIdleEnabled,
|
|
&dwDataSize)) )
|
|
{
|
|
AssertSz(0,"Unable to query User IdleEnabledKey");
|
|
dwIdleEnabled = FALSE;
|
|
}
|
|
|
|
RegCloseKey(hKeyUser);
|
|
|
|
// update the toplevel IdleSyncInfo
|
|
RegUpdateIdleKeyValue(hkeyIdleSync,dwTopLevelDefaultValue);
|
|
|
|
RegCloseKey(hkeyIdleSync);
|
|
|
|
CMutexRegistry.Leave();
|
|
|
|
RegRegisterForIdleTrigger(dwIdleEnabled,ulWaitMinutes,fRunOnBatteries);
|
|
|
|
return TRUE;
|
|
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
EH_Err2:
|
|
RegCloseKey(hkeyIdleSync);
|
|
EH_Err:
|
|
CMutexRegistry.Leave();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: RegRegisterForIdleTrigger()
|
|
|
|
Summary: Sets or removes the Idle trigger.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegRegisterForIdleTrigger(BOOL fRegister,ULONG ulWaitMinutes,BOOL fRunOnBatteries)
|
|
{
|
|
HRESULT hr;
|
|
CSyncMgrSynchronize *pSyncMgrSynchronize;
|
|
LPSYNCSCHEDULEMGR pScheduleMgr;
|
|
|
|
// Review - Currently the mobsync dll is registered as apartment
|
|
// and this function can be called from Logon/Logoff which is FreeThreaded
|
|
// Correct fix is to change DLL to be registered as BOTH but until then
|
|
// just create the class directly.
|
|
|
|
#ifdef _WHENREGUPDATED
|
|
hr = CoCreateInstance(CLSID_SyncMgr,NULL,CLSCTX_ALL,
|
|
IID_ISyncScheduleMgr,(void **) &pScheduleMgr);
|
|
#endif // _WHENREGUPDATED
|
|
|
|
pSyncMgrSynchronize = new CSyncMgrSynchronize;
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
if (pSyncMgrSynchronize)
|
|
{
|
|
hr = pSyncMgrSynchronize->QueryInterface(IID_ISyncScheduleMgr,(void **) &pScheduleMgr);
|
|
pSyncMgrSynchronize->Release();
|
|
}
|
|
|
|
|
|
if (NOERROR != hr)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (fRegister)
|
|
{
|
|
ISyncSchedule *pSyncSchedule = NULL;
|
|
SYNCSCHEDULECOOKIE SyncScheduleCookie;
|
|
BOOL fNewlyCreated = FALSE;
|
|
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
SyncScheduleCookie = GUID_IDLESCHEDULE;
|
|
|
|
// if there isn't an existing schedule create one, else update
|
|
// the existing.
|
|
|
|
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == (hr = pScheduleMgr->OpenSchedule(&SyncScheduleCookie,0,&pSyncSchedule)))
|
|
{
|
|
SyncScheduleCookie = GUID_IDLESCHEDULE;
|
|
// see if it is an exiting schedule.
|
|
|
|
hr = pScheduleMgr->CreateSchedule(L"Idle",0,&SyncScheduleCookie,&pSyncSchedule);
|
|
fNewlyCreated = TRUE;
|
|
}
|
|
|
|
// If created or found a schedule update the trigger settings.
|
|
if (NOERROR == hr)
|
|
{
|
|
ITaskTrigger *pTrigger;
|
|
|
|
pSyncSchedule->SetFlags(SYNCSCHEDINFO_FLAGS_READONLY | SYNCSCHEDINFO_FLAGS_HIDDEN);
|
|
|
|
if (NOERROR == pSyncSchedule->GetTrigger(&pTrigger))
|
|
{
|
|
TASK_TRIGGER trigger;
|
|
ITask *pTask;
|
|
|
|
trigger.cbTriggerSize = sizeof(TASK_TRIGGER);
|
|
|
|
if (SUCCEEDED(pTrigger->GetTrigger(&trigger)))
|
|
{
|
|
DWORD dwFlags;
|
|
|
|
// need to set Idle, ULONG ulWaitMinutes,BOOL fRunOnBatteries
|
|
trigger.cbTriggerSize = sizeof(TASK_TRIGGER);
|
|
trigger.TriggerType = TASK_EVENT_TRIGGER_ON_IDLE;
|
|
trigger.rgFlags = 0;
|
|
pTrigger->SetTrigger(&trigger);
|
|
|
|
if (SUCCEEDED(pSyncSchedule->GetITask(&pTask)))
|
|
{
|
|
// set up if run on battery.
|
|
if (SUCCEEDED(pTask->GetFlags(&dwFlags)))
|
|
{
|
|
dwFlags &= ~TASK_FLAG_DONT_START_IF_ON_BATTERIES;
|
|
dwFlags |= !fRunOnBatteries ? TASK_FLAG_DONT_START_IF_ON_BATTERIES : 0;
|
|
|
|
dwFlags |= TASK_FLAG_RUN_ONLY_IF_LOGGED_ON; // don't require password.
|
|
|
|
pTask->SetFlags(dwFlags);
|
|
}
|
|
|
|
// if this schedule was just created, get the current user name and reset
|
|
// account information password to NULL, If existing schedule don't change
|
|
// since user may have added a password for schedule to run while not logged on.
|
|
if (fNewlyCreated)
|
|
{
|
|
TCHAR szAccountName[MAX_DOMANDANDMACHINENAMESIZE];
|
|
WCHAR *pszAccountName = NULL;
|
|
DWORD dwAccountName = sizeof(szAccountName);
|
|
#ifndef _UNICODE
|
|
WCHAR pwszDomainAndUser[MAX_DOMANDANDMACHINENAMESIZE];
|
|
#endif // _UNICODE
|
|
|
|
// Review, this never returns an errorl
|
|
*szAccountName = TCHAR('\0');
|
|
GetDefaultDomainAndUserName( (LPTSTR) &szAccountName,TEXT("\\"),dwAccountName);
|
|
|
|
#ifndef _UNICODE
|
|
|
|
// if we are compiled as ansi need to convert to wchar
|
|
pszAccountName = pwszDomainAndUser;
|
|
MultiByteToWideChar(CP_ACP, 0, szAccountName, -1, pwszDomainAndUser,sizeof(pwszDomainAndUser));
|
|
#else
|
|
pszAccountName = szAccountName;
|
|
#endif _UNICODE
|
|
|
|
Assert(pszAccountName);
|
|
|
|
if (pszAccountName)
|
|
{
|
|
pTask->SetAccountInformation(pszAccountName,NULL);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// set up the IdleWaitTime.
|
|
pTask->SetIdleWait((WORD) ulWaitMinutes,1);
|
|
|
|
// turn off the option to kill task after xxx minutes.
|
|
pTask->SetMaxRunTime(INFINITE);
|
|
|
|
pTask->Release();
|
|
}
|
|
|
|
pTrigger->Release();
|
|
|
|
}
|
|
|
|
pSyncSchedule->Save();
|
|
}
|
|
|
|
|
|
|
|
pSyncSchedule->Release();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
SYNCSCHEDULECOOKIE SyncScheduleCookie = GUID_IDLESCHEDULE;
|
|
|
|
// see if there is an existing schedule and if so remove it.
|
|
pScheduleMgr->RemoveSchedule(&SyncScheduleCookie);
|
|
|
|
}
|
|
|
|
pScheduleMgr->Release();
|
|
|
|
// set the temporary sens flags according so it can start on an idle trigger.
|
|
// not an error to not be able to get and set key since sens will
|
|
// be running anyways eventually.
|
|
HKEY hkeyAutoSync;
|
|
DWORD dwFlags = 0;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
hkeyAutoSync = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_WRITE | KEY_READ,TRUE);
|
|
if (NULL == hkeyAutoSync)
|
|
{
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
}
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyAutoSync,TEXT("Flags"),NULL, &dwType,
|
|
(LPBYTE) &(dwFlags),&dwDataSize))
|
|
{
|
|
// Here we are setting Idle only so retail the other settings.
|
|
dwFlags &= ~AUTOSYNC_IDLE;
|
|
dwFlags |= (fRegister? AUTOSYNC_IDLE : 0);
|
|
|
|
RegSetValueEx(hkeyAutoSync,TEXT("Flags"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwFlags), sizeof(DWORD));
|
|
}
|
|
RegCloseKey(hkeyAutoSync);
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
BOOL RegGetSyncSettings(DWORD dwSyncType,LPCONNECTIONSETTINGS lpConnectionSettings)
|
|
|
|
Summary: Get ConnectionSettings appropriate to the synctype..
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegGetSyncSettings(DWORD dwSyncType,LPCONNECTIONSETTINGS lpConnectionSettings)
|
|
{
|
|
|
|
switch(dwSyncType)
|
|
{
|
|
case SYNCTYPE_AUTOSYNC:
|
|
return RegGetAutoSyncSettings(lpConnectionSettings);
|
|
break;
|
|
case SYNCTYPE_IDLE:
|
|
return RegGetIdleSyncSettings(lpConnectionSettings);
|
|
break;
|
|
default:
|
|
AssertSz(0,"Unknown SyncType in RegGetSyncSettings");
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Manual Sync Registry Functions
|
|
|
|
***************************************************************************F-F*/
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
BOOL RegRemoveManualSyncSettings(TCHAR *pszTaskName)
|
|
|
|
Summary: Remove the manual settings info from the registry.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegRemoveManualSyncSettings(TCHAR *pszConnectionName)
|
|
{
|
|
HKEY hkeyUser;
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
hkeyUser = RegGetCurrentUserKey(SYNCTYPE_MANUAL,KEY_WRITE | KEY_READ,FALSE);
|
|
|
|
if (hkeyUser)
|
|
{
|
|
RegDeleteKeyNT(hkeyUser, pszConnectionName);
|
|
RegCloseKey(hkeyUser);
|
|
}
|
|
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
}
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
BOOL RegWriteEvents(BOOL fWanLogon,BOOL fWanLogoff,BOOL fLanLogon,BOOL fLanLogoff)
|
|
|
|
Summary: Write out the Wan/Lan Logon/Logoff preferences fo SENS knows whether to invoke us.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
// Run key under HKLM
|
|
const WCHAR wszRunKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
|
|
const WCHAR wszRunKeyCommandLine[] = TEXT("%SystemRoot%\\system32\\mobsync.exe /logon");
|
|
|
|
|
|
STDAPI_(BOOL) RegWriteEvents(BOOL Logon,BOOL Logoff)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkeyAutoSync;
|
|
DWORD dwFlags = 0;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
hkeyAutoSync = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_WRITE | KEY_READ,TRUE);
|
|
if (NULL == hkeyAutoSync)
|
|
{
|
|
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
}
|
|
|
|
RegQueryValueEx(hkeyAutoSync,TEXT("Flags"),NULL, &dwType,
|
|
(LPBYTE) &(dwFlags),
|
|
&dwDataSize);
|
|
|
|
|
|
// Review, Shouldn't need to worry about schedule/idle once IsNetworkAlive
|
|
// is setup properly. Leave for now first time anyone sets idle or schedule
|
|
// stuck
|
|
|
|
|
|
// Here we are setting autosync only,
|
|
// so retain the registry settings for scheduled and idle.
|
|
|
|
dwFlags &= ~(AUTOSYNC_WAN_LOGON | AUTOSYNC_LAN_LOGON | AUTOSYNC_LOGONWITHRUNKEY
|
|
| AUTOSYNC_WAN_LOGOFF | AUTOSYNC_LAN_LOGOFF);
|
|
|
|
// don't set logoff flags unless on platform logoff is supported
|
|
//
|
|
// !!! warning, if you change this also need to update settings
|
|
// and registry which are the other places we block this.
|
|
if ((VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId
|
|
&& g_OSVersionInfo.dwMajorVersion >= 5) )
|
|
{
|
|
dwFlags |= (Logoff ? AUTOSYNC_WAN_LOGOFF : 0);
|
|
dwFlags |= (Logoff ? AUTOSYNC_LAN_LOGOFF : 0);
|
|
}
|
|
|
|
// Since now use Run key instead of SENS always set both Logon Flags
|
|
// that SENS looks for to do a CreateProcess on us to FALSE.
|
|
// Then set the AUTOSYNC_LOGONWITHRUNKEY key to true so sens still gets loaded.
|
|
|
|
dwFlags |= (Logon ? AUTOSYNC_LOGONWITHRUNKEY : 0);
|
|
|
|
hr = RegSetValueEx(hkeyAutoSync,TEXT("Flags"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwFlags), sizeof(DWORD));
|
|
|
|
RegCloseKey(hkeyAutoSync);
|
|
|
|
// now add /delete the run key appropriately.
|
|
|
|
|
|
HKEY hKeyRun;
|
|
|
|
// call private RegOpen since don't want to set security on RunKey
|
|
if (ERROR_SUCCESS == RegOpenKeyExXp(HKEY_LOCAL_MACHINE,wszRunKey,
|
|
NULL,KEY_READ | KEY_WRITE,&hKeyRun,FALSE /*fSetSecurity*/))
|
|
{
|
|
if (Logon)
|
|
{
|
|
RegSetValueEx(hKeyRun, SZ_SYNCMGRNAME, 0, REG_EXPAND_SZ,
|
|
(BYTE *) wszRunKeyCommandLine,(lstrlen(wszRunKeyCommandLine) + 1)*sizeof(TCHAR));
|
|
}
|
|
else
|
|
{
|
|
RegDeleteValue(hKeyRun, SZ_SYNCMGRNAME);
|
|
}
|
|
|
|
RegCloseKey(hKeyRun);
|
|
}
|
|
else
|
|
{
|
|
// if can't open run key try calling SENS if that fails give up.
|
|
SyncMgrExecCmd_UpdateRunKey(Logon);
|
|
}
|
|
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
BOOL RegFixRunKey(BOOL fScheduled)
|
|
|
|
Summary: The original version of SyncMgr for WinMe/Win2000 wrote the
|
|
"run" value as "mobsync.exe /logon". Since this is not a fully-
|
|
qualified path to the mobsync.exe image, the system's search
|
|
path is utilized to locate the image. This can create an
|
|
opportunity for someone to build a 'trojan' mobsync.exe, place
|
|
it in the search path ahead of the real mobsync.exe and have
|
|
the 'trojan' code run whenever a synchronization is invoked.
|
|
To fix this, the path must be stored in the registry using
|
|
fully-qualified syntax.
|
|
|
|
i.e. "%SystemRoot%\System32\mobsync.exe /logon"
|
|
|
|
This function is called from DllRegisterServer to correct this
|
|
registry entry during setup.
|
|
|
|
Returns: Always returns TRUE.
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegFixRunKey(void)
|
|
{
|
|
HKEY hKeyRun;
|
|
|
|
// call private RegOpen since don't want to set security on RunKey
|
|
if (ERROR_SUCCESS == RegOpenKeyExXp(HKEY_LOCAL_MACHINE,
|
|
wszRunKey,
|
|
NULL,
|
|
KEY_READ | KEY_WRITE,
|
|
&hKeyRun,
|
|
FALSE /*fSetSecurity*/))
|
|
{
|
|
TCHAR szRunValue[MAX_PATH];
|
|
DWORD cbValue = sizeof(szRunValue);
|
|
DWORD dwType;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKeyRun,
|
|
SZ_SYNCMGRNAME,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)szRunValue,
|
|
&cbValue))
|
|
{
|
|
if (REG_SZ == dwType && 0 == lstrcmp(szRunValue, TEXT("mobsync.exe /logon")))
|
|
{
|
|
//
|
|
// Upgrade only if it's our original value.
|
|
//
|
|
RegSetValueEx(hKeyRun,
|
|
SZ_SYNCMGRNAME,
|
|
0,
|
|
REG_EXPAND_SZ,
|
|
(BYTE *)wszRunKeyCommandLine,
|
|
(lstrlen(wszRunKeyCommandLine) + 1) * sizeof(TCHAR));
|
|
}
|
|
}
|
|
RegCloseKey(hKeyRun);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
BOOL RegRegisterForScheduledTasks(BOOL fScheduled)
|
|
|
|
Summary: Register/unregister for scheduled tasks
|
|
so SENS knows whether to invoke us.
|
|
|
|
Returns: Returns TRUE if successful, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
|
|
STDAPI_(BOOL) RegRegisterForScheduledTasks(BOOL fScheduled)
|
|
{
|
|
HKEY hkeyAutoSync;
|
|
DWORD dwFlags = 0;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
hkeyAutoSync = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_WRITE | KEY_READ,TRUE);
|
|
|
|
if (NULL == hkeyAutoSync)
|
|
{
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
}
|
|
|
|
RegQueryValueEx(hkeyAutoSync,TEXT("Flags"),NULL, &dwType,
|
|
(LPBYTE) &(dwFlags), &dwDataSize);
|
|
|
|
|
|
// Here we are setting schedsync only,
|
|
// so retain the registry settings for autosync and idle.
|
|
|
|
dwFlags &= AUTOSYNC_WAN_LOGON |
|
|
AUTOSYNC_WAN_LOGOFF |
|
|
AUTOSYNC_LAN_LOGON |
|
|
AUTOSYNC_LAN_LOGOFF |
|
|
AUTOSYNC_IDLE;
|
|
|
|
dwFlags |= (fScheduled? AUTOSYNC_SCHEDULED : 0);
|
|
|
|
RegSetValueEx(hkeyAutoSync,TEXT("Flags"),NULL, REG_DWORD,
|
|
(LPBYTE) &(dwFlags), sizeof(DWORD));
|
|
|
|
RegCloseKey(hkeyAutoSync);
|
|
|
|
CMutexRegistry.Leave();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: RegGetCombinedUserRegFlags, private
|
|
//
|
|
// Synopsis: Gets an or'ing together of user settings for setting up globals.
|
|
//
|
|
// Arguments: [dwSyncMgrRegisterFlags] - On Success gets set to flags
|
|
// on failure they are set to zero
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 24-Aug-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL RegGetCombinedUserRegFlags(DWORD *pdwSyncMgrRegisterFlags)
|
|
{
|
|
HKEY hkey;
|
|
BOOL fResult = TRUE;
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
|
|
|
|
*pdwSyncMgrRegisterFlags = 0;
|
|
|
|
// update the AutoSync Key
|
|
hkey = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_READ,FALSE);
|
|
|
|
if (hkey)
|
|
{
|
|
DWORD dwUserLogonLogoff;
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey,TEXT("Logon"),NULL, &dwType,
|
|
(LPBYTE) &dwUserLogonLogoff,
|
|
&dwDataSize) )
|
|
{
|
|
*pdwSyncMgrRegisterFlags |= dwUserLogonLogoff ? SYNCMGRREGISTERFLAG_CONNECT : 0;
|
|
}
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey,TEXT("Logoff"),NULL, &dwType,
|
|
(LPBYTE) &dwUserLogonLogoff,
|
|
&dwDataSize) )
|
|
{
|
|
*pdwSyncMgrRegisterFlags |= dwUserLogonLogoff ? SYNCMGRREGISTERFLAG_PENDINGDISCONNECT : 0;
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
|
|
// update the Idle Key
|
|
hkey = RegGetSyncTypeKey(SYNCTYPE_IDLE,KEY_READ,FALSE);
|
|
|
|
if (hkey)
|
|
{
|
|
DWORD dwIdleEnabled;
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey,TEXT("IdleEnabled"),NULL, &dwType,
|
|
(LPBYTE) &dwIdleEnabled,
|
|
&dwDataSize) )
|
|
{
|
|
*pdwSyncMgrRegisterFlags |= dwIdleEnabled ? SYNCMGRREGISTERFLAG_IDLE : 0;
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
return TRUE; // always return true but don't set flags on error.
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: RegGetCombinedHandlerRegFlags, private
|
|
//
|
|
// Synopsis: Gets an or'ing together of handler registration Keys
|
|
//
|
|
// Arguments: [dwSyncMgrRegisterFlags] - On Success gets set to flags
|
|
// on failure they are set to zero
|
|
// [ft] - On Success filed with timestamp
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 24-Aug-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL RegGetCombinedHandlerRegFlags(DWORD *pdwSyncMgrRegisterFlags,FILETIME *pft)
|
|
{
|
|
HKEY hkey;
|
|
BOOL fResult = TRUE;
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
|
|
|
|
*pdwSyncMgrRegisterFlags = 0;
|
|
|
|
hkey = RegGetHandlerTopLevelKey(KEY_READ);
|
|
|
|
if (hkey)
|
|
{
|
|
DWORD dwRegistrationFlags;
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey,SZ_REGISTRATIONFLAGSKEY,NULL, &dwType,
|
|
(LPBYTE) &dwRegistrationFlags,
|
|
&dwDataSize) )
|
|
{
|
|
*pdwSyncMgrRegisterFlags = dwRegistrationFlags;
|
|
}
|
|
|
|
RegGetTimeStamp(hkey,pft);
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
return TRUE; // always return true but don't set flags on error.
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: RegGetChangedHandlerFlags, private
|
|
//
|
|
// Synopsis: Gets an or'ing together of handler registration Keys
|
|
// that have changed since the given FILETIME
|
|
//
|
|
// Arguments: [pft] - Pointer to FileTime for Compare
|
|
// [pdwChangedFlags] - On Success filed with flags that channged
|
|
//
|
|
// Returns: TRUE if could gather flags.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 24-Aug-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL RegGetChangedHandlerFlags(FILETIME *pft,DWORD *pdwHandlerChandedFlags)
|
|
{
|
|
HKEY hkeyHandler;
|
|
|
|
*pdwHandlerChandedFlags = 0;
|
|
|
|
hkeyHandler = RegGetHandlerTopLevelKey(KEY_READ);
|
|
|
|
if (hkeyHandler)
|
|
{
|
|
TCHAR lpName[MAX_PATH + 1];
|
|
DWORD cbName = MAX_PATH;
|
|
DWORD dwRegistrationFlags = 0;
|
|
FILETIME ftHandlerReg;
|
|
DWORD dwIndex = 0;
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD dwHandlerRegFlags;
|
|
LONG lRet;
|
|
HKEY hKeyClsid;
|
|
|
|
// enumerate the keys
|
|
while ( ERROR_SUCCESS == RegEnumKey(hkeyHandler,dwIndex,lpName,cbName) )
|
|
{
|
|
lRet = RegOpenKeyEx( hkeyHandler,
|
|
lpName,
|
|
NULL,
|
|
KEY_READ,
|
|
&hKeyClsid );
|
|
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
|
|
RegGetTimeStamp(hKeyClsid,&ftHandlerReg);
|
|
|
|
// handler reg is new time than our gvien time add it to the flags.
|
|
if (CompareFileTime(pft,&ftHandlerReg) < 0)
|
|
{
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKeyClsid,SZ_REGISTRATIONFLAGSKEY,NULL, &dwType,
|
|
(LPBYTE) &dwHandlerRegFlags,
|
|
&dwDataSize) )
|
|
{
|
|
dwRegistrationFlags |= dwHandlerRegFlags;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKeyClsid);
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
|
|
*pdwHandlerChandedFlags = dwRegistrationFlags;
|
|
|
|
RegCloseKey(hkeyHandler);
|
|
}
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: RegRegisterForEvents, private
|
|
//
|
|
// Synopsis: Registers/UnRegisters for appropriate SENS and WinLogon Events.
|
|
// and any other per machine registration we need to do
|
|
//
|
|
// Arguments: [fUninstall] - set to true by uninstall to force us to unregister
|
|
// regardless of current machine state.
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
// !!!Warning - Assumes toplevel key information is up to date.
|
|
|
|
STDAPI RegRegisterForEvents(BOOL fUninstall)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
BOOL fLogon = FALSE;
|
|
BOOL fLogoff = FALSE;
|
|
BOOL fIdle = FALSE;
|
|
#ifdef _SENS
|
|
IEventSystem *pEventSystem;
|
|
#endif // _SENS
|
|
CCriticalSection cCritSect(&g_DllCriticalSection,GetCurrentThreadId());
|
|
|
|
cCritSect.Enter();
|
|
|
|
if (!fUninstall)
|
|
{
|
|
FILETIME ftHandlerReg;
|
|
DWORD dwSyncMgrUsersRegisterFlags; // or'ing of all Users settings
|
|
DWORD dwSyncMgrHandlerRegisterFlags; // or'ing of all handler settings.
|
|
DWORD dwCombinedFlags; // or together user and handler.
|
|
|
|
// if not an uninstall determine the true machine state
|
|
// if Logon set for handler or user set or if handler
|
|
// wants an idle set.
|
|
// If Logoff set we register for Logoff.
|
|
|
|
RegGetCombinedUserRegFlags(&dwSyncMgrUsersRegisterFlags);
|
|
RegGetCombinedHandlerRegFlags(&dwSyncMgrHandlerRegisterFlags,&ftHandlerReg);
|
|
|
|
dwCombinedFlags = dwSyncMgrUsersRegisterFlags | dwSyncMgrHandlerRegisterFlags;
|
|
|
|
if ( (dwCombinedFlags & SYNCMGRREGISTERFLAG_CONNECT)
|
|
|| (dwSyncMgrHandlerRegisterFlags & SYNCMGRREGISTERFLAG_IDLE) )
|
|
{
|
|
fLogon = TRUE;
|
|
}
|
|
|
|
if ( (dwCombinedFlags & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) )
|
|
{
|
|
fLogoff = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
// update Registry entries for SENS to lookup
|
|
RegWriteEvents(fLogon,fLogoff);
|
|
|
|
#ifdef _SENS
|
|
|
|
|
|
// we were able to load ole automation so reg/unreg with the event system.
|
|
hr = CoCreateInstance(CLSID_CEventSystem,NULL,CLSCTX_SERVER,IID_IEventSystem,
|
|
(LPVOID *) &pEventSystem);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IEventSubscription *pIEventSubscription;
|
|
WCHAR szGuid[GUID_SIZE+1];
|
|
BSTR bstrSubscriberID = NULL;
|
|
BSTR bstrPROGID_EventSubscription = NULL;
|
|
|
|
|
|
bstrPROGID_EventSubscription = SysAllocString(PROGID_EventSubscription);
|
|
|
|
StringFromGUID2(GUID_SENSSUBSCRIBER_SYNCMGRP,szGuid, GUID_SIZE);
|
|
bstrSubscriberID = SysAllocString(szGuid);
|
|
|
|
if (bstrSubscriberID && bstrPROGID_EventSubscription)
|
|
{
|
|
// register for RasConnect
|
|
hr = CoCreateInstance(
|
|
CLSID_CEventSubscription,
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
IID_IEventSubscription,
|
|
(LPVOID *) &pIEventSubscription
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR bstrPublisherID = NULL;
|
|
BSTR bstrSubscriptionID = NULL;
|
|
BSTR bstrSubscriptionName = NULL;
|
|
BSTR bstrSubscriberCLSID = NULL;
|
|
BSTR bstrEventID = NULL;
|
|
BSTR bstrEventClassID = NULL;
|
|
BSTR bstrIID = NULL;
|
|
|
|
// if there are any events, register with ens for messages.
|
|
if (fLogon)
|
|
{
|
|
|
|
StringFromGUID2(GUID_SENSLOGONSUBSCRIPTION_SYNCMGRP,szGuid, GUID_SIZE);
|
|
bstrSubscriptionID = SysAllocString(szGuid);
|
|
|
|
if (bstrSubscriptionID && SUCCEEDED(hr))
|
|
{
|
|
hr = pIEventSubscription->put_SubscriptionID(bstrSubscriptionID);
|
|
}
|
|
|
|
StringFromGUID2(CLSID_SyncMgrp,szGuid, GUID_SIZE);
|
|
bstrSubscriberCLSID = SysAllocString(szGuid);
|
|
|
|
if (bstrSubscriberCLSID && SUCCEEDED(hr))
|
|
{
|
|
hr = pIEventSubscription->put_SubscriberCLSID(bstrSubscriberCLSID);
|
|
}
|
|
|
|
StringFromGUID2(SENSGUID_PUBLISHER,szGuid, GUID_SIZE);
|
|
bstrPublisherID = SysAllocString(szGuid);
|
|
if (bstrPublisherID && SUCCEEDED(hr))
|
|
{
|
|
hr = pIEventSubscription->put_PublisherID(bstrPublisherID);
|
|
}
|
|
|
|
|
|
bstrSubscriptionName = SysAllocString(SZ_SYNCMGRNAME);
|
|
if (bstrSubscriptionName && SUCCEEDED(hr))
|
|
{
|
|
hr = pIEventSubscription->put_SubscriptionName(bstrSubscriptionName);
|
|
}
|
|
|
|
bstrEventID = SysAllocString(L"ConnectionMade");
|
|
if (bstrEventID && SUCCEEDED(hr))
|
|
{
|
|
hr = pIEventSubscription->put_MethodName(bstrEventID);
|
|
}
|
|
|
|
StringFromGUID2(SENSGUID_EVENTCLASS_NETWORK,szGuid,GUID_SIZE);
|
|
bstrEventClassID = SysAllocString(szGuid);
|
|
if (bstrEventClassID && SUCCEEDED(hr))
|
|
{
|
|
hr = pIEventSubscription->put_EventClassID(bstrEventClassID);
|
|
}
|
|
|
|
// set this up for roaming
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// hr = pIEventSubscription->put_PerUser(TRUE); // don't register PerUser for Nw
|
|
}
|
|
|
|
StringFromGUID2(IID_ISensNetwork,szGuid,GUID_SIZE);
|
|
bstrIID = SysAllocString(szGuid);
|
|
if (bstrIID && SUCCEEDED(hr))
|
|
{
|
|
hr = pIEventSubscription->put_InterfaceID(bstrIID);
|
|
}
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pEventSystem->Store(bstrPROGID_EventSubscription,pIEventSubscription);
|
|
}
|
|
|
|
if (bstrIID)
|
|
{
|
|
SysFreeString(bstrIID);
|
|
}
|
|
|
|
if (bstrPublisherID)
|
|
SysFreeString(bstrPublisherID);
|
|
|
|
if (bstrSubscriberCLSID)
|
|
SysFreeString(bstrSubscriberCLSID);
|
|
|
|
if (bstrEventClassID)
|
|
SysFreeString(bstrEventClassID);
|
|
|
|
if (bstrEventID)
|
|
SysFreeString(bstrEventID);
|
|
|
|
if (bstrSubscriptionID)
|
|
SysFreeString(bstrSubscriptionID);
|
|
|
|
if (bstrSubscriptionName)
|
|
SysFreeString(bstrSubscriptionName);
|
|
}
|
|
else // don't need to be registered, remove.
|
|
{
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
int errorIndex;
|
|
|
|
bstrSubscriptionID = SysAllocString(L"SubscriptionID={6295df30-35ee-11d1-8707-00C04FD93327}");
|
|
|
|
if (bstrSubscriptionID)
|
|
{
|
|
hr = pEventSystem->Remove(bstrPROGID_EventSubscription,bstrSubscriptionID /* QUERY */,&errorIndex);
|
|
SysFreeString(bstrSubscriptionID);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
pIEventSubscription->Release();
|
|
|
|
}
|
|
|
|
if (bstrSubscriberID)
|
|
{
|
|
SysFreeString(bstrSubscriberID);
|
|
}
|
|
|
|
if (bstrPROGID_EventSubscription)
|
|
{
|
|
SysFreeString(bstrPROGID_EventSubscription);
|
|
}
|
|
|
|
pEventSystem->Release();
|
|
|
|
}
|
|
|
|
#endif // _SENS
|
|
|
|
cCritSect.Leave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
// helper functions for handler registration
|
|
STDAPI_(BOOL) RegGetTimeStamp(HKEY hKey, FILETIME *pft)
|
|
{
|
|
DWORD dwType;
|
|
FILETIME ft;
|
|
LONG lr;
|
|
DWORD dwSize = sizeof(FILETIME);
|
|
|
|
Assert(pft);
|
|
|
|
lr = RegQueryValueEx( hKey,
|
|
SZ_REGISTRATIONTIMESTAMPKEY,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)&ft,
|
|
&dwSize );
|
|
|
|
|
|
if ( lr == ERROR_SUCCESS )
|
|
{
|
|
Assert( dwSize == sizeof(FILETIME) && dwType == REG_BINARY );
|
|
*pft = ft;
|
|
}
|
|
else
|
|
{
|
|
// set the filetime to way back when to
|
|
// any compares will just say older instead
|
|
// of having to check success code
|
|
(*pft).dwLowDateTime = 0;
|
|
(*pft).dwHighDateTime = 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
STDAPI_(BOOL) RegWriteTimeStamp(HKEY hkey)
|
|
{
|
|
SYSTEMTIME sysTime;
|
|
FILETIME ft;
|
|
LONG lr = -1;
|
|
|
|
GetSystemTime(&sysTime); // void can't check for errors
|
|
|
|
if (SystemTimeToFileTime(&sysTime,&ft) )
|
|
{
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
|
|
// write out the UpdateTime
|
|
lr = RegSetValueEx( hkey,
|
|
SZ_REGISTRATIONTIMESTAMPKEY,
|
|
NULL,
|
|
REG_BINARY,
|
|
(BYTE *)&ft,
|
|
sizeof(ft) );
|
|
|
|
CMutexRegistry.Leave();
|
|
|
|
}
|
|
return (ERROR_SUCCESS == lr) ? TRUE : FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: UpdateHandlerKeyInformation
|
|
//
|
|
// Synopsis: Updates the top-level handler key information
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: void
|
|
//
|
|
// Modifies: enumerates the handlers underneath the given key
|
|
// updating the registrationFlags which is an || or
|
|
// all registered handler flags and then updates the
|
|
// timestamp on this key
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void UpdateHandlerKeyInformation(HKEY hKeyHandler)
|
|
{
|
|
DWORD dwSyncMgrTopLevelRegisterFlags = 0;
|
|
DWORD dwIndex = 0;
|
|
TCHAR lpName[MAX_PATH];
|
|
DWORD cbName = MAX_PATH;
|
|
|
|
|
|
while ( ERROR_SUCCESS == RegEnumKey(hKeyHandler,dwIndex,
|
|
lpName,cbName) )
|
|
{
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD dwHandlerRegFlags;
|
|
LONG lRet;
|
|
HKEY hKeyClsid;
|
|
|
|
lRet = RegOpenKeyEx( hKeyHandler,
|
|
lpName,
|
|
NULL,
|
|
KEY_READ,
|
|
&hKeyClsid );
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKeyClsid,SZ_REGISTRATIONFLAGSKEY,NULL, &dwType,
|
|
(LPBYTE) &dwHandlerRegFlags,
|
|
&dwDataSize) )
|
|
{
|
|
dwSyncMgrTopLevelRegisterFlags |= dwHandlerRegFlags;
|
|
}
|
|
|
|
RegCloseKey(hKeyClsid);
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
|
|
// not much we can do if RegFlags are messed up other than assert and mask out
|
|
Assert(dwSyncMgrTopLevelRegisterFlags <= SYNCMGRREGISTERFLAGS_MASK);
|
|
dwSyncMgrTopLevelRegisterFlags &= SYNCMGRREGISTERFLAGS_MASK;
|
|
|
|
// write out new flags even if errors occured. work thing that happens is
|
|
// we don't set up someones autosync automatically.
|
|
RegSetValueEx(hKeyHandler,SZ_REGISTRATIONFLAGSKEY,NULL, REG_DWORD,
|
|
(LPBYTE) &(dwSyncMgrTopLevelRegisterFlags), sizeof(DWORD));
|
|
|
|
RegWriteTimeStamp(hKeyHandler);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegUpdateTopLevelKeys
|
|
//
|
|
// Synopsis: Looks at toplevel AutoSync,Idle, etc. keys and determines
|
|
// if they need to be updated and if so goes for it.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: set pfFirstRegistration out param to true if this is
|
|
// the first handler that has registered so we can setup defaults.
|
|
//
|
|
// History: 24-Aug-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(void) RegUpdateTopLevelKeys()
|
|
{
|
|
HKEY hkey;
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
|
|
CMutexRegistry.Enter();
|
|
|
|
|
|
// update the AutoSync Key
|
|
hkey = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_READ | KEY_WRITE,TRUE);
|
|
|
|
if (hkey)
|
|
{
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD dwUserLogonLogoff;
|
|
|
|
// see if has a logon value and if it is either newly created or
|
|
// old format. Call Update to setthings up
|
|
if (ERROR_SUCCESS != RegQueryValueEx(hkey,TEXT("Logon"),NULL, &dwType,
|
|
(LPBYTE) &dwUserLogonLogoff,
|
|
&dwDataSize) )
|
|
{
|
|
RegUpdateAutoSyncKeyValue(hkey,-1,-1);
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
|
|
// update the Idle Key
|
|
hkey = RegGetSyncTypeKey(SYNCTYPE_IDLE,KEY_READ | KEY_WRITE,TRUE);
|
|
|
|
if (hkey)
|
|
{
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
DWORD dwIdleEnabled;
|
|
|
|
// see if has a Idle value and if it is either newly created or
|
|
// old format. Call Update to setthings up
|
|
if (ERROR_SUCCESS != RegQueryValueEx(hkey,TEXT("IdleEnabled"),NULL, &dwType,
|
|
(LPBYTE) &dwIdleEnabled,
|
|
&dwDataSize) )
|
|
{
|
|
RegUpdateIdleKeyValue(hkey,-1);
|
|
}
|
|
|
|
|
|
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
CMutexRegistry.Leave();
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegRegisterHandler
|
|
//
|
|
// Synopsis: Registers Handlers with SyncMgr.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: set pfFirstRegistration out param to true if this is
|
|
// the first handler that has registered so we can setup defaults.
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(BOOL) RegRegisterHandler(REFCLSID rclsidHandler,
|
|
WCHAR const* pwszDescription,
|
|
DWORD dwSyncMgrRegisterFlags,
|
|
BOOL *pfFirstRegistration)
|
|
{
|
|
LONG lRet;
|
|
|
|
RegUpdateTopLevelKeys(); // make sure other top-level keys are up to date.
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
*pfFirstRegistration = FALSE;
|
|
HKEY hKeyHandler;
|
|
|
|
hKeyHandler = RegGetHandlerTopLevelKey(KEY_READ | KEY_WRITE);
|
|
|
|
if (NULL == hKeyHandler)
|
|
{
|
|
CMutexRegistry.Leave();
|
|
return FALSE;
|
|
}
|
|
|
|
XRegKey xRegKeyHandler( hKeyHandler );
|
|
|
|
//
|
|
// Check if this is the first handler being registerd
|
|
//
|
|
TCHAR szGuid[GUID_SIZE+1];
|
|
DWORD cbGuid = GUID_SIZE+1;
|
|
|
|
lRet = RegEnumKeyEx( hKeyHandler,
|
|
0,
|
|
szGuid,
|
|
&cbGuid,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( lRet != ERROR_SUCCESS )
|
|
*pfFirstRegistration = TRUE;
|
|
|
|
//
|
|
// Convert guid and description to TCHAR
|
|
//
|
|
TCHAR *pszDesc;
|
|
BOOL fOk = FALSE;
|
|
|
|
StringFromGUID2( rclsidHandler, szGuid, GUID_SIZE+1 );
|
|
pszDesc = (TCHAR *)pwszDescription;
|
|
|
|
|
|
// write out the registration flags. If fail go ahead
|
|
// and succed registration anyways.
|
|
if (hKeyHandler)
|
|
{
|
|
HKEY hKeyClsid;
|
|
|
|
hKeyClsid = RegGetHandlerKey(hKeyHandler,szGuid,KEY_WRITE | KEY_READ,TRUE);
|
|
|
|
if (hKeyClsid)
|
|
{
|
|
|
|
fOk = TRUE; // if make handle key say registered okay
|
|
|
|
if (pszDesc)
|
|
{
|
|
RegSetValueEx(hKeyClsid,NULL,NULL, REG_SZ,
|
|
(LPBYTE) pszDesc,
|
|
(lstrlen(pszDesc) +1)*sizeof(TCHAR));
|
|
}
|
|
|
|
RegSetValueEx(hKeyClsid,SZ_REGISTRATIONFLAGSKEY,NULL, REG_DWORD,
|
|
(LPBYTE) &(dwSyncMgrRegisterFlags), sizeof(DWORD));
|
|
|
|
// update the TimeStamp on the handler clsid
|
|
|
|
RegWriteTimeStamp(hKeyClsid);
|
|
RegCloseKey( hKeyClsid );
|
|
|
|
// update the toplevel key
|
|
UpdateHandlerKeyInformation(hKeyHandler);
|
|
}
|
|
}
|
|
|
|
// update the user information.
|
|
RegSetUserDefaults();
|
|
RegRegisterForEvents(FALSE /* fUninstall */);
|
|
|
|
CMutexRegistry.Leave();
|
|
|
|
return fOk;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegRegRemoveHandler
|
|
//
|
|
// Synopsis: UnRegisters Handlers with SyncMgr.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: set pfAllHandlerUnRegistered out param to true if this is
|
|
// the last handler that needs to be unregistered before
|
|
// turning off our defaults..
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(BOOL) RegRegRemoveHandler(REFCLSID rclsidHandler)
|
|
{
|
|
HKEY hKeyHandler;
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
|
|
CMutexRegistry.Enter();
|
|
|
|
|
|
hKeyHandler = RegGetHandlerTopLevelKey(KEY_WRITE | KEY_READ);
|
|
|
|
if (NULL == hKeyHandler)
|
|
{
|
|
//
|
|
// Non-existent key, so nothing to remove
|
|
//
|
|
CMutexRegistry.Leave();
|
|
return TRUE;
|
|
}
|
|
|
|
XRegKey xKeyHandler( hKeyHandler );
|
|
|
|
TCHAR szGuid[GUID_SIZE+1];
|
|
|
|
#ifdef _UNICODE
|
|
StringFromGUID2( rclsidHandler, szGuid, GUID_SIZE+1 );
|
|
#else
|
|
WCHAR wszGuid[GUID_SIZE+1];
|
|
StringFromGUID2( rclsidHandler, wszGuid, GUID_SIZE+1 );
|
|
|
|
BOOL fOk = ConvertString( szGuid, wszGuid, GUID_SIZE+1 );
|
|
Assert( fOk );
|
|
#endif
|
|
|
|
HKEY hKeyClsid;
|
|
|
|
hKeyClsid = RegGetHandlerKey(hKeyHandler,szGuid,KEY_WRITE | KEY_READ,FALSE);
|
|
|
|
if (hKeyClsid)
|
|
{
|
|
RegCloseKey( hKeyClsid );
|
|
RegDeleteKey( hKeyHandler, szGuid );
|
|
|
|
// update the toplevel key
|
|
UpdateHandlerKeyInformation(hKeyHandler);
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Non-existent key, so nothing to remove
|
|
//
|
|
}
|
|
|
|
|
|
RegRegisterForEvents(FALSE /* fUninstall */); // UPDATE EVENT REGISTRATION.
|
|
|
|
CMutexRegistry.Leave();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegGetHandlerRegistrationInfo
|
|
//
|
|
// Synopsis: Gets Information of the specified handler.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: pdwSyncMgrRegisterFlags
|
|
//
|
|
// History: 20-Aug-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(BOOL) RegGetHandlerRegistrationInfo(REFCLSID rclsidHandler,LPDWORD pdwSyncMgrRegisterFlags)
|
|
{
|
|
HKEY hKeyHandler;
|
|
|
|
*pdwSyncMgrRegisterFlags = 0;
|
|
|
|
|
|
hKeyHandler = RegGetHandlerTopLevelKey(KEY_READ);
|
|
|
|
if (NULL == hKeyHandler)
|
|
{
|
|
//
|
|
// Non-existent key
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
XRegKey xKeyHandler( hKeyHandler );
|
|
|
|
TCHAR szGuid[GUID_SIZE+1];
|
|
|
|
#ifdef _UNICODE
|
|
StringFromGUID2( rclsidHandler, szGuid, GUID_SIZE+1 );
|
|
#else
|
|
WCHAR wszGuid[GUID_SIZE+1];
|
|
StringFromGUID2( rclsidHandler, wszGuid, GUID_SIZE+1 );
|
|
|
|
BOOL fOk = ConvertString( szGuid, wszGuid, GUID_SIZE+1 );
|
|
Assert( fOk );
|
|
#endif
|
|
|
|
HKEY hKeyClsid;
|
|
BOOL fResult = FALSE;
|
|
|
|
hKeyClsid = RegGetHandlerKey(hKeyHandler,szGuid,KEY_READ,FALSE);
|
|
|
|
if (hKeyClsid)
|
|
{
|
|
DWORD dwType = REG_DWORD ;
|
|
DWORD dwDataSize = sizeof(DWORD);
|
|
LONG lRet;
|
|
|
|
lRet = RegQueryValueEx(hKeyClsid,SZ_REGISTRATIONFLAGSKEY,NULL, &dwType,
|
|
(LPBYTE) pdwSyncMgrRegisterFlags,
|
|
&dwDataSize);
|
|
RegCloseKey( hKeyClsid );
|
|
|
|
fResult = (ERROR_SUCCESS == lRet) ? TRUE : FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Non-existent key, so nothing to remove
|
|
//
|
|
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegSetUserDefaults
|
|
//
|
|
// Synopsis: Registers default values for auto and idle sync
|
|
//
|
|
// Setup based on Handler and UserPreferences
|
|
//
|
|
// History: 20-May-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(void) RegSetUserDefaults()
|
|
{
|
|
HKEY hKeyUser = NULL;
|
|
BOOL fLogon = FALSE;
|
|
BOOL fLogoff = FALSE;
|
|
FILETIME ftHandlerReg;
|
|
DWORD dwHandlerRegistrationFlags;
|
|
|
|
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
|
|
CMutexRegistry.Enter();
|
|
|
|
// get the combined handler registration toplevel flags and timeStamp
|
|
// to see if should bother enumerating the rest.
|
|
if (!RegGetCombinedHandlerRegFlags(&dwHandlerRegistrationFlags,&ftHandlerReg))
|
|
{
|
|
CMutexRegistry.Leave();
|
|
return;
|
|
}
|
|
|
|
if (0 != (dwHandlerRegistrationFlags &
|
|
(SYNCMGRREGISTERFLAG_CONNECT | SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) ) )
|
|
{
|
|
|
|
// See if AutoSync key needs to be updated
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_AUTOSYNC,KEY_WRITE | KEY_READ,TRUE);
|
|
|
|
if (hKeyUser)
|
|
{
|
|
FILETIME ftUserAutoSync;
|
|
|
|
// if got the User get the timestamp and see if it is older than the handlers
|
|
// If this is a new user filetime will be 0
|
|
|
|
RegGetTimeStamp(hKeyUser,&ftUserAutoSync);
|
|
|
|
if (CompareFileTime(&ftUserAutoSync,&ftHandlerReg) < 0)
|
|
{
|
|
DWORD dwHandlerChangedFlags;
|
|
|
|
// need to walk through handlers and update what we need to set based
|
|
// on each handlers timestamp since we don't want a handler that registered
|
|
// for idle to cause us to turn AutoSync back on and vis-a-versa
|
|
|
|
if (RegGetChangedHandlerFlags(&ftUserAutoSync,&dwHandlerChangedFlags))
|
|
{
|
|
BOOL fLogon = (dwHandlerChangedFlags & SYNCMGRREGISTERFLAG_CONNECT) ? TRUE : FALSE;
|
|
BOOL fLogoff = (dwHandlerChangedFlags & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) ? TRUE : FALSE;
|
|
|
|
RegSetAutoSyncDefaults(fLogon,fLogoff);
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey(hKeyUser);
|
|
hKeyUser = NULL;
|
|
}
|
|
}
|
|
|
|
if (0 != (dwHandlerRegistrationFlags & SYNCMGRREGISTERFLAG_IDLE ) )
|
|
{
|
|
|
|
// now check for Idle same logic as above could probably combine
|
|
// into a function
|
|
// See if AutoSync key needs to be updated
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_IDLE, KEY_WRITE | KEY_READ,TRUE);
|
|
|
|
|
|
if (hKeyUser)
|
|
{
|
|
FILETIME ftUserIdleSync;
|
|
|
|
// if got the User get the timestamp and see if it is older than the handlers
|
|
// If this is a new user filetime will be 0
|
|
|
|
RegGetTimeStamp(hKeyUser,&ftUserIdleSync);
|
|
|
|
if (CompareFileTime(&ftUserIdleSync,&ftHandlerReg) < 0)
|
|
{
|
|
DWORD dwHandlerChangedFlags;
|
|
|
|
// need to walk through handlers and update what we need to set based
|
|
// on each handlers timestamp since we don't want a handler that registered
|
|
// for AutoSync to cause us to turn Idle back on and vis-a-versa
|
|
|
|
if (RegGetChangedHandlerFlags(&ftUserIdleSync,&dwHandlerChangedFlags))
|
|
{
|
|
if (dwHandlerChangedFlags & SYNCMGRREGISTERFLAG_IDLE)
|
|
{
|
|
RegSetIdleSyncDefaults(TRUE);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey(hKeyUser);
|
|
hKeyUser = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
CMutexRegistry.Leave();
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegSetAutoSyncDefaults
|
|
//
|
|
// Synopsis: Registers default values for auto sync
|
|
//
|
|
// History: 20-May-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(void) RegSetAutoSyncDefaults(BOOL fLogon,BOOL fLogoff)
|
|
{
|
|
CONNECTIONSETTINGS *pConnection = (LPCONNECTIONSETTINGS)
|
|
ALLOC(sizeof(CONNECTIONSETTINGS));
|
|
if ( pConnection == 0 )
|
|
return;
|
|
|
|
XPtr<CONNECTIONSETTINGS> xConnection( pConnection );
|
|
|
|
INT iRet = LoadString(g_hmodThisDll,
|
|
IDS_LAN_CONNECTION,
|
|
pConnection->pszConnectionName,
|
|
ARRAYLEN(pConnection->pszConnectionName) );
|
|
Assert( iRet != 0 );
|
|
|
|
// -1 values are ignored by RegSetAutoSyncSettings.
|
|
// if not turning on leave the User Preferences alone,
|
|
pConnection->dwConnType = 0;
|
|
pConnection->dwLogon = fLogon ? TRUE : -1;
|
|
pConnection->dwLogoff = fLogoff ? TRUE : -1;
|
|
pConnection->dwPromptMeFirst = -1;
|
|
pConnection->dwMakeConnection = -1;
|
|
pConnection->dwIdleEnabled = -1;
|
|
|
|
// since this bases settings on what is already set no need to
|
|
// do a cleanreg or update the machine state
|
|
RegSetAutoSyncSettings(pConnection, 1, 0,
|
|
FALSE /* fCleanReg */,
|
|
FALSE /* fSetMachineState */,
|
|
FALSE /* fPerUser */);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegSetUserAutoSyncDefaults
|
|
//
|
|
// Synopsis: Registers user default values for auto sync
|
|
//
|
|
// History: 39-March-99 rogerg Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI RegSetUserAutoSyncDefaults(DWORD dwSyncMgrRegisterMask,
|
|
DWORD dwSyncMgrRegisterFlags)
|
|
{
|
|
|
|
// if not changing either logon or logoff just return
|
|
if (!(dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_CONNECT)
|
|
&& !(dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) )
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
CONNECTIONSETTINGS *pConnection = (LPCONNECTIONSETTINGS)
|
|
ALLOC(sizeof(CONNECTIONSETTINGS));
|
|
if ( pConnection == 0 )
|
|
return E_OUTOFMEMORY;
|
|
|
|
XPtr<CONNECTIONSETTINGS> xConnection( pConnection );
|
|
|
|
INT iRet = LoadString(g_hmodThisDll,
|
|
IDS_LAN_CONNECTION,
|
|
pConnection->pszConnectionName,
|
|
ARRAYLEN(pConnection->pszConnectionName) );
|
|
Assert( iRet != 0 );
|
|
|
|
// -1 values are ignored by RegSetAutoSyncSettings.
|
|
// if not turning on leave the User Preferences alone,
|
|
pConnection->dwConnType = 0;
|
|
pConnection->dwLogon = -1;
|
|
pConnection->dwLogoff = -1;
|
|
pConnection->dwPromptMeFirst = -1;
|
|
pConnection->dwMakeConnection = -1;
|
|
pConnection->dwIdleEnabled = -1;
|
|
|
|
if (dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_CONNECT)
|
|
{
|
|
pConnection->dwLogon = (dwSyncMgrRegisterFlags & SYNCMGRREGISTERFLAG_CONNECT)
|
|
? TRUE : FALSE;
|
|
}
|
|
|
|
if (dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT)
|
|
{
|
|
pConnection->dwLogoff = (dwSyncMgrRegisterFlags & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT)
|
|
? TRUE : FALSE;
|
|
}
|
|
|
|
// since this bases settings on what is already set no need to
|
|
// do a cleanreg or update the machine state
|
|
RegSetAutoSyncSettings(pConnection, 1, 0,
|
|
FALSE /* fCleanReg */,
|
|
TRUE /* fSetMachineState */,
|
|
TRUE /* fPerUser */);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegSetIdleSyncDefaults
|
|
//
|
|
// Synopsis: Registers default values for idle sync
|
|
//
|
|
// History: 20-May-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(void) RegSetIdleSyncDefaults(BOOL fIdle)
|
|
{
|
|
|
|
Assert(fIdle); // for now this should only be called when true;
|
|
|
|
if (!fIdle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CONNECTIONSETTINGS *pConnection = (LPCONNECTIONSETTINGS)
|
|
ALLOC(sizeof(CONNECTIONSETTINGS));
|
|
if ( pConnection == 0 )
|
|
return;
|
|
|
|
XPtr<CONNECTIONSETTINGS> xConnection( pConnection );
|
|
|
|
INT iRet = LoadString(g_hmodThisDll,
|
|
IDS_LAN_CONNECTION,
|
|
pConnection->pszConnectionName,
|
|
ARRAYLEN(pConnection->pszConnectionName) );
|
|
Assert( iRet != 0 );
|
|
|
|
pConnection->dwConnType = 0;
|
|
pConnection->dwLogon = -1;
|
|
pConnection->dwLogoff = -1;
|
|
pConnection->dwPromptMeFirst = -1;
|
|
pConnection->dwMakeConnection = -1;
|
|
pConnection->dwIdleEnabled = TRUE;
|
|
|
|
// set all userLevel items to -1 so user gets the defaults if new
|
|
// but keep their settings if have already tweaked them.
|
|
pConnection->ulIdleRetryMinutes = -1;
|
|
pConnection->ulDelayIdleShutDownTime = -1;
|
|
pConnection->dwRepeatSynchronization = -1;
|
|
pConnection->ulIdleWaitMinutes = -1;
|
|
pConnection->dwRunOnBatteries = -1;
|
|
|
|
RegSetIdleSyncSettings(pConnection, 1, 0,
|
|
FALSE /* fCleanReg */,
|
|
FALSE /* fPerUser */);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegSetIdleSyncDefaults
|
|
//
|
|
// Synopsis: Registers default values for idle sync
|
|
//
|
|
// History: 30-March-99 ROGERG Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI RegSetUserIdleSyncDefaults(DWORD dwSyncMgrRegisterMask,
|
|
DWORD dwSyncMgrRegisterFlags)
|
|
{
|
|
|
|
// RegSetIdleSyncSettings doesn't handle idle enabled of -1 so only
|
|
// call if Idle actually is set in the flags, if not just return
|
|
|
|
if (!(dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_IDLE))
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
CONNECTIONSETTINGS *pConnection = (LPCONNECTIONSETTINGS)
|
|
ALLOC(sizeof(CONNECTIONSETTINGS));
|
|
if ( pConnection == 0 )
|
|
return E_OUTOFMEMORY;
|
|
|
|
XPtr<CONNECTIONSETTINGS> xConnection( pConnection );
|
|
|
|
INT iRet = LoadString(g_hmodThisDll,
|
|
IDS_LAN_CONNECTION,
|
|
pConnection->pszConnectionName,
|
|
ARRAYLEN(pConnection->pszConnectionName) );
|
|
Assert( iRet != 0 );
|
|
|
|
pConnection->dwConnType = 0;
|
|
pConnection->dwLogon = -1;
|
|
pConnection->dwLogoff = -1;
|
|
pConnection->dwPromptMeFirst = -1;
|
|
pConnection->dwMakeConnection = -1;
|
|
|
|
pConnection->dwIdleEnabled = (SYNCMGRREGISTERFLAG_IDLE & dwSyncMgrRegisterFlags)
|
|
? TRUE : FALSE;
|
|
|
|
// set all userLevel items to -1 so user gets the defaults if new
|
|
// but keep their settings if have already tweaked them.
|
|
pConnection->ulIdleRetryMinutes = -1;
|
|
pConnection->ulDelayIdleShutDownTime = -1;
|
|
pConnection->dwRepeatSynchronization = -1;
|
|
pConnection->ulIdleWaitMinutes = -1;
|
|
pConnection->dwRunOnBatteries = -1;
|
|
|
|
RegSetIdleSyncSettings(pConnection, 1, 0,
|
|
FALSE /* fCleanReg */,
|
|
TRUE /* fPerUser */);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegGetUserRegisterFlags
|
|
//
|
|
// Synopsis: returns current registration flags for the User.
|
|
//
|
|
// History: 30-March-99 ROGERG Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI RegGetUserRegisterFlags(LPDWORD pdwSyncMgrRegisterFlags)
|
|
{
|
|
CONNECTIONSETTINGS connectSettings;
|
|
|
|
*pdwSyncMgrRegisterFlags = 0;
|
|
|
|
INT iRet = LoadString(g_hmodThisDll,
|
|
IDS_LAN_CONNECTION,
|
|
connectSettings.pszConnectionName,
|
|
ARRAYLEN(connectSettings.pszConnectionName) );
|
|
if (0 == iRet)
|
|
{
|
|
Assert( iRet != 0 );
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
RegGetSyncSettings(SYNCTYPE_AUTOSYNC,&connectSettings);
|
|
|
|
if (connectSettings.dwLogon)
|
|
{
|
|
*pdwSyncMgrRegisterFlags |= (SYNCMGRREGISTERFLAG_CONNECT);
|
|
}
|
|
|
|
if (connectSettings.dwLogoff)
|
|
{
|
|
*pdwSyncMgrRegisterFlags |= (SYNCMGRREGISTERFLAG_PENDINGDISCONNECT);
|
|
}
|
|
|
|
|
|
RegGetSyncSettings(SYNCTYPE_IDLE,&connectSettings);
|
|
|
|
if (connectSettings.dwIdleEnabled)
|
|
{
|
|
*pdwSyncMgrRegisterFlags |= (SYNCMGRREGISTERFLAG_IDLE);
|
|
}
|
|
|
|
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function: BOOL RegSchedHandlerItemsChecked(TCHAR *pszHandlerName,
|
|
TCHAR *pszConnectionName,
|
|
TCHAR *pszScheduleName)
|
|
|
|
Summary: Determine if any items are checked on this handler for this schedule
|
|
|
|
Returns: Returns TRUE if one or more are checked, FALSE otherwise
|
|
|
|
------------------------------------------------------------------------F-F*/
|
|
BOOL RegSchedHandlerItemsChecked(TCHAR *pszHandlerName,
|
|
TCHAR *pszConnectionName,
|
|
TCHAR *pszScheduleName)
|
|
{
|
|
SCODE sc;
|
|
HKEY hKeyUser,
|
|
hkeySchedName,
|
|
hkeyConnection,
|
|
hkeyHandler,
|
|
hkeyItem;
|
|
DWORD cbName = MAX_PATH,
|
|
dwIndex = 0,
|
|
dwCheckState = 0,
|
|
dwType = REG_DWORD,
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
BOOL fItemsChecked = FALSE;
|
|
TCHAR lpName[MAX_PATH + 1];
|
|
|
|
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE);
|
|
|
|
if (NULL == hKeyUser)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
smChkTo(EH_Err3,RegOpenKeyEx (hKeyUser,
|
|
pszScheduleName,0,KEY_READ,
|
|
&hkeySchedName));
|
|
|
|
smChkTo(EH_Err4,RegOpenKeyEx (hkeySchedName,
|
|
pszConnectionName,
|
|
0,KEY_READ,
|
|
&hkeyConnection));
|
|
|
|
smChkTo(EH_Err5,RegOpenKeyEx (hkeyConnection,
|
|
pszHandlerName,
|
|
0,KEY_READ,
|
|
&hkeyHandler));
|
|
// need to enum handler items.
|
|
while ( ERROR_SUCCESS == RegEnumKey(hkeyHandler,dwIndex,
|
|
lpName,cbName) )
|
|
{
|
|
LONG lRet;
|
|
|
|
lRet = RegOpenKeyEx( hkeyHandler,
|
|
lpName,
|
|
NULL,
|
|
KEY_READ,
|
|
&hkeyItem);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
RegQueryValueEx(hkeyItem,TEXT("CheckState"),
|
|
NULL, &dwType, (LPBYTE) &dwCheckState, &dwDataSize);
|
|
|
|
RegCloseKey(hkeyItem);
|
|
|
|
}
|
|
else
|
|
{
|
|
goto EH_Err5;
|
|
}
|
|
|
|
if (dwCheckState)
|
|
{
|
|
fItemsChecked = TRUE;
|
|
break;
|
|
}
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hkeyHandler);
|
|
RegCloseKey(hkeyConnection);
|
|
RegCloseKey(hkeySchedName);
|
|
RegCloseKey(hKeyUser);
|
|
return fItemsChecked;
|
|
|
|
EH_Err5:
|
|
RegCloseKey(hkeyConnection);
|
|
EH_Err4:
|
|
RegCloseKey(hkeySchedName);
|
|
EH_Err3:
|
|
RegCloseKey(hKeyUser);
|
|
|
|
return fItemsChecked;
|
|
}
|
|
|