You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
621 lines
17 KiB
621 lines
17 KiB
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "shlwapi.h"
|
|
#include "parse.h"
|
|
|
|
#include "wbemcli.h"
|
|
#include "SComPtr.h"
|
|
#include "rsop.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Reads all RSOP_IERegistryPolicySetting instances in the namespace and
|
|
// stores them in a list.
|
|
/////////////////////////////////////////////////////////////////////
|
|
CRSOPRegData::CRSOPRegData():
|
|
m_pData(NULL)
|
|
{
|
|
}
|
|
|
|
CRSOPRegData::~CRSOPRegData()
|
|
{
|
|
Free();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
void CRSOPRegData::Free()
|
|
{
|
|
__try
|
|
{
|
|
if (NULL != m_pData)
|
|
{
|
|
LPRSOPREGITEM lpTemp;
|
|
do
|
|
{
|
|
lpTemp = m_pData->pNext;
|
|
if (m_pData->lpData)
|
|
LocalFree (m_pData->lpData);
|
|
|
|
LocalFree (m_pData);
|
|
m_pData = lpTemp;
|
|
} while (lpTemp);
|
|
}
|
|
}
|
|
__except(TRUE)
|
|
{
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
HRESULT CRSOPRegData::Initialize(BSTR bstrNamespace)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
__try
|
|
{
|
|
_bstr_t bstrWQL = L"WQL";
|
|
_bstr_t bstrQuery = L"SELECT currentUser, registryKey, valueName, valueType, value, deleted, precedence, GPOID, command FROM RSOP_IERegistryPolicySetting";
|
|
_bstr_t bstrRegistryKey = L"registryKey";
|
|
_bstr_t bstrCurrentUser = L"currentUser";
|
|
_bstr_t bstrValueName = L"valueName";
|
|
_bstr_t bstrValueType = L"valueType";
|
|
_bstr_t bstrValue = L"value";
|
|
_bstr_t bstrDeleted = L"deleted";
|
|
_bstr_t bstrPrecedence = L"precedence";
|
|
_bstr_t bstrGPOid = L"GPOID";
|
|
_bstr_t bstrCommand = L"command";
|
|
|
|
// Create an instance of the WMI locator service
|
|
ComPtr<IWbemLocator> pIWbemLocator = NULL;
|
|
hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator, (LPVOID *) &pIWbemLocator);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Connect to the server
|
|
ComPtr<IWbemServices> pIWbemServices = NULL;
|
|
hr = pIWbemLocator->ConnectServer(bstrNamespace, NULL, NULL, 0L, 0L, NULL,
|
|
NULL, &pIWbemServices);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Execute the query
|
|
ComPtr<IEnumWbemClassObject> pEnum = NULL;
|
|
hr = pIWbemServices->ExecQuery (bstrWQL, bstrQuery,
|
|
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
|
NULL, &pEnum);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Loop through the results
|
|
ComPtr<IWbemClassObject> pRegObj = NULL;
|
|
ULONG ulRet = 0;
|
|
hr = pEnum->Next(WBEM_INFINITE, 1, &pRegObj, &ulRet);
|
|
while (S_OK == hr && 0 != ulRet) // ulRet == 0 is "data not available" case
|
|
{
|
|
// Get the deleted flag & registry key
|
|
_variant_t varDeleted;
|
|
_variant_t varRegistryKey;
|
|
hr = pRegObj->Get (bstrDeleted, 0, &varDeleted, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
hr = pRegObj->Get (bstrRegistryKey, 0, &varRegistryKey, NULL, NULL);
|
|
|
|
// Get the class (current user or local machine)
|
|
_variant_t varCurUser;
|
|
if (SUCCEEDED(hr))
|
|
hr = pRegObj->Get (bstrCurrentUser, 0, &varCurUser, NULL, NULL);
|
|
|
|
// Get the value name
|
|
_variant_t varValueName;
|
|
if (SUCCEEDED(hr))
|
|
hr = pRegObj->Get (bstrValueName, 0, &varValueName, NULL, NULL);
|
|
|
|
// Get the value type
|
|
_variant_t varValueType;
|
|
if (SUCCEEDED(hr))
|
|
hr = pRegObj->Get (bstrValueType, 0, &varValueType, NULL, NULL);
|
|
|
|
// Get the value data
|
|
_variant_t varData;
|
|
if (SUCCEEDED(hr))
|
|
hr = pRegObj->Get (bstrValue, 0, &varData, NULL, NULL);
|
|
|
|
// Get the precedence
|
|
_variant_t varPrecedence;
|
|
if (SUCCEEDED(hr))
|
|
hr = pRegObj->Get (bstrPrecedence, 0, &varPrecedence, NULL, NULL);
|
|
|
|
// Get the command
|
|
_variant_t varCommand;
|
|
if (SUCCEEDED(hr))
|
|
hr = pRegObj->Get (bstrCommand, 0, &varCommand, NULL, NULL);
|
|
|
|
// Get the GPO ID
|
|
_variant_t varGPOid;
|
|
if (SUCCEEDED(hr))
|
|
hr = pRegObj->Get (bstrGPOid, 0, &varGPOid, NULL, NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPTSTR lpGPOName;
|
|
hr = GetGPOFriendlyName (pIWbemServices, varGPOid.bstrVal,
|
|
bstrWQL, &lpGPOName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR bstrValueTemp = NULL;
|
|
if (varValueName.vt != VT_NULL)
|
|
bstrValueTemp = varValueName.bstrVal;
|
|
|
|
DWORD dwDataSize = 0;
|
|
LPBYTE lpData = NULL;
|
|
if (varData.vt != VT_NULL)
|
|
{
|
|
SAFEARRAY *pSafeArray = varData.parray;
|
|
dwDataSize = pSafeArray->rgsabound[0].cElements;
|
|
lpData = (LPBYTE) pSafeArray->pvData;
|
|
}
|
|
|
|
if ((varValueType.uintVal == REG_NONE) && bstrValueTemp &&
|
|
!lstrcmpi(bstrValueTemp, TEXT("**command")))
|
|
{
|
|
bstrValueTemp = varCommand.bstrVal;
|
|
dwDataSize = 0;
|
|
lpData = NULL;
|
|
}
|
|
|
|
AddNode((varCurUser.boolVal == 0) ? FALSE : TRUE,
|
|
varRegistryKey.bstrVal, bstrValueTemp,
|
|
varValueType.uintVal, dwDataSize, lpData,
|
|
varPrecedence.uintVal, lpGPOName,
|
|
(varDeleted.boolVal == 0) ? FALSE : TRUE);
|
|
|
|
LocalFree (lpGPOName);
|
|
}
|
|
}
|
|
|
|
hr = pEnum->Next(WBEM_INFINITE, 1, &pRegObj, &ulRet);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
__except(TRUE)
|
|
{
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
HRESULT CRSOPRegData::GetGPOFriendlyName(IWbemServices *pIWbemServices,
|
|
LPTSTR lpGPOID, BSTR bstrLanguage,
|
|
LPTSTR *pGPOName)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
__try
|
|
{
|
|
// Set the default
|
|
*pGPOName = NULL;
|
|
|
|
// Build the query
|
|
ComPtr<IEnumWbemClassObject> pEnum = NULL;
|
|
LPTSTR lpQuery = (LPTSTR) LocalAlloc (LPTR, ((lstrlen(lpGPOID) + 50) * sizeof(TCHAR)));
|
|
if (NULL != lpQuery)
|
|
{
|
|
wsprintf (lpQuery, TEXT("SELECT name, id FROM RSOP_GPO where id=\"%s\""), lpGPOID);
|
|
_bstr_t bstrQuery = lpQuery;
|
|
|
|
// Execute the query
|
|
hr = pIWbemServices->ExecQuery(bstrLanguage, bstrQuery,
|
|
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
|
NULL, &pEnum);
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
ComPtr<IWbemClassObject> pGPOObj;
|
|
ULONG nObjects = 0;
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Loop through the results
|
|
hr = pEnum->Next(WBEM_INFINITE, 1, &pGPOObj, &nObjects);
|
|
}
|
|
|
|
_bstr_t bstrName = L"name";
|
|
_variant_t varGPOName;
|
|
if (SUCCEEDED(hr) && nObjects > 0)
|
|
{
|
|
// Get the name
|
|
hr = pGPOObj->Get(bstrName, 0, &varGPOName, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Save the name
|
|
*pGPOName = (LPTSTR) LocalAlloc (LPTR, (lstrlen(varGPOName.bstrVal) + 1) * sizeof(TCHAR));
|
|
if (*pGPOName)
|
|
{
|
|
_bstr_t bstrVal = varGPOName.bstrVal;
|
|
lstrcpy (*pGPOName, (LPCTSTR)bstrVal);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
|
|
}
|
|
|
|
}
|
|
// Check for the "data not available case"
|
|
else if (nObjects == 0)
|
|
hr = S_OK;
|
|
|
|
if (lpQuery)
|
|
LocalFree (lpQuery);
|
|
}
|
|
__except(TRUE)
|
|
{
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
BOOL CRSOPRegData::AddNode(BOOL bHKCU, BSTR bstrKeyName, BSTR bstrValueName,
|
|
DWORD dwType, DWORD dwDataSize, LPBYTE lpData,
|
|
UINT uiPrecedence, LPTSTR lpGPOName, BOOL bDeleted)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
__try
|
|
{
|
|
// Calculate the size of the new registry item
|
|
DWORD dwSize = sizeof (RSOPREGITEM);
|
|
if (bstrKeyName)
|
|
dwSize += ((SysStringLen(bstrKeyName) + 1) * sizeof(WCHAR));
|
|
if (bstrValueName)
|
|
dwSize += ((SysStringLen(bstrValueName) + 1) * sizeof(WCHAR));
|
|
if (lpGPOName)
|
|
dwSize += ((SysStringLen(lpGPOName) + 1) * sizeof(TCHAR));
|
|
|
|
// Allocate space for it
|
|
LPRSOPREGITEM lpItem = (LPRSOPREGITEM) LocalAlloc (LPTR, dwSize);
|
|
if (!lpItem)
|
|
return FALSE;
|
|
|
|
// Fill in item
|
|
lpItem->bHKCU = bHKCU;
|
|
lpItem->dwType = dwType;
|
|
lpItem->dwSize = dwDataSize;
|
|
lpItem->uiPrecedence = uiPrecedence;
|
|
lpItem->bDeleted = bDeleted;
|
|
|
|
if (bstrKeyName)
|
|
{
|
|
lpItem->lpKeyName = (LPTSTR)(((LPBYTE)lpItem) + sizeof(RSOPREGITEM));
|
|
lstrcpy (lpItem->lpKeyName, (LPCTSTR)bstrKeyName);
|
|
}
|
|
|
|
if (bstrValueName)
|
|
{
|
|
if (bstrKeyName)
|
|
lpItem->lpValueName = lpItem->lpKeyName + lstrlen (lpItem->lpKeyName) + 1;
|
|
else
|
|
lpItem->lpValueName = (LPTSTR)(((LPBYTE)lpItem) + sizeof(RSOPREGITEM));
|
|
|
|
lstrcpy (lpItem->lpValueName, (LPCTSTR)bstrValueName);
|
|
}
|
|
|
|
if (lpGPOName)
|
|
{
|
|
if (bstrValueName)
|
|
lpItem->lpGPOName = lpItem->lpValueName + lstrlen (lpItem->lpValueName) + 1;
|
|
else
|
|
{
|
|
if (bstrKeyName)
|
|
lpItem->lpGPOName = lpItem->lpKeyName + lstrlen (lpItem->lpKeyName) + 1;
|
|
else
|
|
lpItem->lpGPOName = (LPTSTR)(((LPBYTE)lpItem) + sizeof(RSOPREGITEM));
|
|
}
|
|
|
|
lstrcpy (lpItem->lpGPOName, lpGPOName);
|
|
}
|
|
|
|
if (lpData)
|
|
{
|
|
lpItem->lpData = (LPBYTE) LocalAlloc (LPTR, dwDataSize);
|
|
if (!lpItem->lpData)
|
|
{
|
|
LocalFree (lpItem);
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory (lpItem->lpData, lpData, dwDataSize);
|
|
}
|
|
|
|
// Add item to link list
|
|
lpItem->pNext = m_pData;
|
|
m_pData = lpItem;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
__except(TRUE)
|
|
{
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
const TCHAR szDELETEPREFIX[] = TEXT("**del.");
|
|
|
|
#ifndef NORM_STOP_ON_NULL
|
|
#define NORM_STOP_ON_NULL 0x10000000
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
UINT CRSOPRegData::ReadValue(UINT uiPrecedence, BOOL bHKCU, LPTSTR pszKeyName,
|
|
LPTSTR pszValueName, LPBYTE pData, DWORD dwMaxSize,
|
|
DWORD *pdwType, LPTSTR *lpGPOName, LPRSOPREGITEM lpItem /*= NULL*/)
|
|
{
|
|
UINT iRet = ERROR_SUCCESS;
|
|
__try
|
|
{
|
|
LPRSOPREGITEM lpTemp = NULL;
|
|
BOOL bDeleted = FALSE;
|
|
LPTSTR lpValueNameTemp = pszValueName;
|
|
|
|
if (!lpItem)
|
|
{
|
|
lpTemp = m_pData;
|
|
|
|
if (pszValueName)
|
|
{
|
|
INT iDelPrefixLen = lstrlen(szDELETEPREFIX);
|
|
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
|
|
pszValueName, iDelPrefixLen,
|
|
szDELETEPREFIX, iDelPrefixLen) == CSTR_EQUAL)
|
|
{
|
|
lpValueNameTemp = pszValueName + iDelPrefixLen;
|
|
bDeleted = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
// Find the item
|
|
while (lpTemp)
|
|
{
|
|
if (pszKeyName && lpValueNameTemp &&
|
|
lpTemp->lpKeyName && lpTemp->lpValueName)
|
|
{
|
|
if (bDeleted == lpTemp->bDeleted)
|
|
{
|
|
if ((uiPrecedence == 0) || (uiPrecedence == (UINT)lpTemp->uiPrecedence))
|
|
{
|
|
if (!lstrcmpi(lpTemp->lpValueName, lpValueNameTemp) &&
|
|
!lstrcmpi(lpTemp->lpKeyName, pszKeyName) &&
|
|
bHKCU == lpTemp->bHKCU)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (!pszKeyName && lpValueNameTemp &&
|
|
!lpTemp->lpKeyName && lpTemp->lpValueName)
|
|
{
|
|
if (bDeleted == lpTemp->bDeleted)
|
|
{
|
|
if ((uiPrecedence == 0) || (uiPrecedence == (UINT)lpTemp->uiPrecedence))
|
|
{
|
|
if (!lstrcmpi(lpTemp->lpValueName, lpValueNameTemp) &&
|
|
bHKCU == lpTemp->bHKCU)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (pszKeyName && !lpValueNameTemp &&
|
|
lpTemp->lpKeyName && !lpTemp->lpValueName)
|
|
{
|
|
if (bDeleted == lpTemp->bDeleted)
|
|
{
|
|
if ((uiPrecedence == 0) || (uiPrecedence == (UINT)lpTemp->uiPrecedence))
|
|
{
|
|
if (!lstrcmpi(lpTemp->lpKeyName, pszKeyName) &&
|
|
bHKCU == lpTemp->bHKCU)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
lpTemp = lpTemp->pNext;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Read a specific item
|
|
lpTemp = lpItem;
|
|
}
|
|
|
|
// Check to see if the item was found
|
|
if (lpTemp)
|
|
{
|
|
// Check if the data will fit in the buffer passed in
|
|
if (lpTemp->dwSize <= dwMaxSize)
|
|
{
|
|
// Copy the data
|
|
if (lpTemp->lpData)
|
|
CopyMemory (pData, lpTemp->lpData, lpTemp->dwSize);
|
|
|
|
*pdwType = lpTemp->dwType;
|
|
|
|
if (lpGPOName)
|
|
*lpGPOName = lpTemp->lpGPOName;
|
|
}
|
|
else
|
|
iRet = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
iRet = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
__except(TRUE)
|
|
{
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
#define MAXSTRLEN 1024
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Reads the reg settings from WMI for a particular ADM file and stores
|
|
// them in a PART array.
|
|
/////////////////////////////////////////////////////////////////////
|
|
void ReadRegSettingsForADM(LPADMFILE admfile, LPPARTDATA pPartData,
|
|
BSTR bstrNamespace)
|
|
{
|
|
__try
|
|
{
|
|
CRSOPRegData RegData;
|
|
RegData.Initialize(bstrNamespace);
|
|
|
|
LPPART part = admfile->pParts;
|
|
for( int i = 0; i < admfile->nParts; i++ )
|
|
{
|
|
BOOL bHKCU = (HKEY_LOCAL_MACHINE == part[i].hkClass) ? FALSE : TRUE;
|
|
BYTE pbData[MAXSTRLEN];
|
|
ZeroMemory(pbData, sizeof(pbData));
|
|
DWORD dwType = REG_NONE;
|
|
LPTSTR lpGPOName = NULL;
|
|
UINT uiRet = RegData.ReadValue(1, bHKCU, part[i].value.szKeyname,
|
|
part[i].value.szValueName, pbData,
|
|
sizeof(pbData), &dwType, &lpGPOName);
|
|
|
|
if ( ERROR_SUCCESS == uiRet)
|
|
{
|
|
// store data as numeric or string
|
|
BOOL fNumeric = FALSE;
|
|
DWORD dwValue = 0;
|
|
_bstr_t bstrValue;
|
|
if (REG_SZ != dwType) // Numeric
|
|
{
|
|
fNumeric = TRUE;
|
|
memcpy(&dwValue, pbData, sizeof(dwValue));
|
|
}
|
|
else
|
|
{
|
|
// string data is always stored as wide strings
|
|
if (NULL != pbData)
|
|
bstrValue = (LPWSTR)pbData;
|
|
}
|
|
|
|
if (pPartData[i].value.szValue != NULL)
|
|
LocalFree(pPartData[i].value.szValue);
|
|
pPartData[i].value.szValue = NULL;
|
|
|
|
if ((part[i].nType == PART_POLICY && part->fRequired) || part[i].nType == PART_CHECKBOX)
|
|
{
|
|
if (fNumeric)
|
|
{
|
|
if (dwValue == (DWORD) part[i].value.nValueOn)
|
|
pPartData[i].value.dwValue = 1;
|
|
else
|
|
pPartData[i].value.dwValue = 0;
|
|
}
|
|
else // String
|
|
{
|
|
if (NULL != part[i].value.szValueOn && NULL != pbData &&
|
|
0 == StrCmp(part[i].value.szValueOn, (LPTSTR)bstrValue))
|
|
{
|
|
pPartData[i].value.dwValue = 1;
|
|
}
|
|
else
|
|
pPartData[i].value.dwValue = 0;
|
|
|
|
if (NULL != pbData)
|
|
pPartData[i].value.szValue = StrDup((LPTSTR)bstrValue);
|
|
}
|
|
pPartData[i].value.fNumeric = TRUE;
|
|
pPartData[i].fSave = TRUE;
|
|
}
|
|
else if (part[i].nType == PART_DROPDOWNLIST)
|
|
{
|
|
if (part[i].nSelectedAction != NO_ACTION && part[i].nActions > 0)
|
|
{
|
|
for(int nIndex = 0; nIndex < part[i].nActions; nIndex++)
|
|
{
|
|
if (fNumeric)
|
|
{
|
|
if (part[i].actionlist[nIndex].dwValue == dwValue && part[i].actionlist[nIndex].szName)
|
|
{
|
|
pPartData[i].value.szValue = StrDup(part[i].actionlist[nIndex].szName);
|
|
pPartData[i].nSelectedAction = nIndex;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (NULL != part[i].actionlist[nIndex].szValue && NULL != pbData &&
|
|
0 == StrCmp(part[i].actionlist[nIndex].szValue, (LPTSTR)bstrValue) &&
|
|
NULL != part[i].actionlist[nIndex].szName)
|
|
{
|
|
pPartData[i].value.szValue = StrDup(part[i].actionlist[nIndex].szName);
|
|
pPartData[i].nSelectedAction = nIndex;
|
|
}
|
|
}
|
|
}
|
|
pPartData[i].fSave = TRUE;
|
|
}
|
|
pPartData[i].value.fNumeric = FALSE;
|
|
}
|
|
else if (part[i].nType == PART_LISTBOX && fNumeric)
|
|
{
|
|
// Allocate memory
|
|
if (pPartData[i].nActions == 0)
|
|
pPartData[i].actionlist = (LPACTIONLIST) HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY, sizeof(ACTIONLIST));
|
|
|
|
if (pPartData[i].actionlist != NULL)
|
|
{
|
|
if (0 == pPartData[i].nActions)
|
|
{
|
|
pPartData[i].nActions = 1;
|
|
pPartData[i].actionlist[0].value = (LPVALUE) HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY, sizeof(VALUE));
|
|
}
|
|
|
|
if (pPartData[i].actionlist[0].value != NULL)
|
|
{
|
|
TCHAR szValueName[10];
|
|
int nItems = pPartData[i].actionlist[0].nValues;
|
|
if (0 != nItems)
|
|
{
|
|
LPVOID lpTemp = (LPVALUE) HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
pPartData[i].actionlist[0].value,
|
|
sizeof(VALUE) * (nItems + 1));
|
|
if (lpTemp != NULL)
|
|
pPartData[i].actionlist[0].value = (LPVALUE)lpTemp;
|
|
else
|
|
continue;
|
|
}
|
|
|
|
if (part[i].value.szKeyname != NULL)
|
|
pPartData[i].actionlist[0].value[nItems].szKeyname = StrDup(part[i].value.szKeyname);
|
|
|
|
wnsprintf(szValueName, ARRAYSIZE(szValueName), TEXT("%d"), nItems + 1);
|
|
pPartData[i].actionlist[0].value[nItems].szValueName = StrDup(szValueName);
|
|
|
|
if (NULL != pbData)
|
|
pPartData[i].actionlist[0].value[nItems].szValue = StrDup((LPTSTR)bstrValue);
|
|
pPartData[i].actionlist[0].nValues++;
|
|
pPartData[i].value.fNumeric = TRUE;
|
|
pPartData[i].value.dwValue = 1;
|
|
pPartData[i].fSave = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (NULL != pbData)
|
|
pPartData[i].value.szValue = StrDup((LPTSTR)bstrValue);
|
|
pPartData[i].value.dwValue = dwValue;
|
|
pPartData[i].value.fNumeric = fNumeric;
|
|
pPartData[i].fSave = TRUE;
|
|
}
|
|
}
|
|
} // end for
|
|
}
|
|
__except(TRUE)
|
|
{
|
|
}
|
|
}
|
|
|