The problem that I am having is that when I call Get to get the
Win32_SecurityDescriptor class, I get a "Not Found" error (0x80041002).
Does anyone have any ideas how that could happen? The same code finds
the Win32_Share class just fine.
The code (sans the error checking) is below.
--
David L. Crow Texas! It's like a
cr...@OrangeBlood.org whole other country.
char * homeShareServer = argv[1];
char * homeFolderDir = argv[2];
char * sAMAccountName = argv[3];
hr = CoInitialize(0);
hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, 0);
IWbemLocator *pLocator = NULL;
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLocator);
IWbemServices *pServices = NULL;
_bstr_t path = L"\\\\" + _bstr_t(homeShareServer) + L"\\root\\cimv2";
hr = pLocator->ConnectServer(path, NULL, NULL, NULL, 0, NULL, NULL,
&pServices);
BSTR sharePath = SysAllocString(L"Win32_Share");
IWbemClassObject *pShareClass = NULL;
hr = pServices->GetObject(sharePath, 0, NULL, &pShareClass, NULL);
BSTR createMethod = SysAllocString(L"Create");
IWbemClassObject *pShareCreateMeth = NULL;
hr = pShareClass->GetMethod(createMethod, 0, &pShareCreateMeth, NULL);
IWbemClassObject *pShareCreate = NULL;
hr = pShareCreateMeth->SpawnInstance(0, &pShareCreate);
VARIANT path;
VariantInit(&path);
V_VT(&path) = VT_BSTR;
_bstr_t pathVal = _bstr_t(homeFolderDir) + L"\\" +
_bstr_t(sAMAccountName);
V_BSTR(&path) = pathVal;
hr = pShareCreate->Put(L"Path", 0, &path, 0);
VariantClear(&path);
VARIANT shareName;
VariantInit(&shareName);
V_VT(&shareName) = VT_BSTR;
_bstr_t shareNameVal = _bstr_t(sAMAccountName) + L"$";
V_BSTR(&shareName) = shareNameVal;
hr = pShareCreate->Put(L"Name", 0, &shareName, 0);
VariantClear(&shareName);
VARIANT shareType;
VariantInit(&shareType);
V_VT(&shareType) = VT_I4;
V_I4(&shareType) = 0;
hr = pShareCreate->Put(L"Type", 0, &shareType, 0);
VariantClear(&shareName);
IWbemClassObject *pSecDescClass = NULL;
BSTR secDescPath = L"Win32_SecurityDescriptor";
hr = pServices->GetObject(secDescPath, 0, NULL, &pSecDescClass, NULL);
IWbemClassObject *pSecDesc = NULL;
hr = pSecDescClass->SpawnInstance(0, &pSecDesc);
When I changed the second line to be
BSTR secDescPath = SysAllocString(L"Win32_SecurityDescriptor");
it fixed things. I was tipped off by turnning on full logging and looking
in the logfiles in C:\WINNT\system32\wbem\Logs .
My next problem is how to get an array of multiple ACE objects into the
DACL property of the SecurityDescriptor.
Any hints on array VARIANT values would be much appreciated.
class Win32_SecurityDescriptor : Win32_MethodParameterClass
{
Win32_Trustee Owner;
Win32_Trustee Group;
Win32_ACE DACL[];
Win32_ACE SACL[];
uint32 ControlFlags;
};
the DACL is an array of instances of Win32_ACE.
In C++ terms this becomes a SAFEARRAY of type VT_ARRAY|CIM_OBJECT
where the array actually contains pointers to the IUknonw interface obtained
from an IWbemClassObject
that is an instance of a Win32_ACE class.
///////////
if it is an option for you, you might evaluate using the NetSahreAdd API,
passing the security descriptor as the shi502_security_descriptor param of
the the SAHRE_INFO_502 struct.
You can obtain the security descriptor easily by string concatenation if you
use the SDDL language.
--
This posting is provided "As Is" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
"David L. Crow" <cr...@waterloo.OrangeBlood.org> wrote in message
news:agdt5l$g22$1...@waterloo.OrangeBlood.org...
I started down the WMI road using Visual Basic where there were lots of
examples and later found out that I was restrictued to cscript 5.1 which
didn't interract very well with being invoked from another application.
Because of the WMI experience I garnered, I stuck it out using WMI from
C++. Over the last two days, I have questioned that strategy :-), but I
am almost there.
> In C++ terms this becomes a SAFEARRAY of type VT_ARRAY|CIM_OBJECT
> where the array actually contains pointers to the IUknonw interface obtained
> from an IWbemClassObject
> that is an instance of a Win32_ACE class.
Here is the code that I am using. Instead of CIM_OBJECT, I was using
VT_UNKNOWN based on some examples that I could find earlier in this
newsgroup.
Right now, I am trying to set two ACE entries on the share. Only the
second one is getting set. The second one is correct (ie the correct
user and access perms), so this leads me to believe that I am not doing
the array thing correctly. I am definitely a newbie in the COM memory
model.
Again, I have removed a bunch of error checking to make it more readable.
//
//
//
IWbemClassObject *
getSecurityDescriptor(IWbemServices *pServices,
char * homeShareServer,
char * domainName,
char * sAMAccountName) {
HRESULT hr;
BSTR secDescClassName = SysAllocString(L"Win32_SecurityDescriptor");
IWbemClassObject *pSecDescClass = NULL;
hr = pServices->GetObject(secDescClassName, 0, NULL, &pSecDescClass, NULL);
SysFreeString(secDescClassName);
IWbemClassObject *pSecDesc = NULL;
hr = pSecDescClass->SpawnInstance(0, &pSecDesc);
pSecDescClass->Release();
IWbemClassObject *userACE =
getACE(pServices, homeShareServer, "Administrators");
IWbemClassObject *adminACE = getACE(pServices, domainName, sAMAccountName);
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound = 1;
aDim[0].cElements = 2;
SAFEARRAY *daclACE = SafeArrayCreate(VT_UNKNOWN, 1, aDim);
long i = 0;
SafeArrayPutElement(daclACE, &i, (IUnknown *)userACE);
i = 1;
SafeArrayPutElement(daclACE, &i, (IUnknown *)adminACE);
VARIANT dacl;
V_VT(&dacl) = VT_ARRAY | VT_UNKNOWN;
V_ARRAY(&dacl) = daclACE;
hr = pSecDesc->Put(L"DACL", 0, &dacl, 0);
return pSecDesc;
}
//
//
//
IWbemClassObject *
getACE(IWbemServices *pServices, char *domainName, char *accountName) {
HRESULT hr;
BSTR trusteeClassName = SysAllocString(L"Win32_Trustee");
IWbemClassObject *pTrusteeClass = NULL;
hr = pServices->GetObject(trusteeClassName, 0, NULL, &pTrusteeClass, NULL);
SysFreeString(trusteeClassName);
IWbemClassObject *pTrustee = NULL;
hr = pTrusteeClass->SpawnInstance(0, &pTrustee);
pTrusteeClass->Release();
char * adminName = (char *)malloc(strlen(domainName) +
strlen(accountName) + 2);
sprintf(adminName, "%s\\%s", domainName, accountName);
IWbemClassObject *pAccount = NULL;
_bstr_t adminPath = L"Win32_Account.Name='" + _bstr_t(accountName) +
L"',Domain='" + _bstr_t(domainName) + L"'";
hr = pServices->GetObject(adminPath, 0, NULL, &pAccount, NULL);
VARIANT pSIDString;
hr = pAccount->Get(L"SID", 0, &pSIDString, NULL, NULL);
pAccount->Release();
IWbemClassObject *pSID = NULL;
_bstr_t sidPath = L"Win32_SID.SID='" + _bstr_t(V_BSTR(&pSIDString)) + L"'";
printf("sidString = %S\n", V_BSTR(&pSIDString));
hr = pServices->GetObject(sidPath, 0, NULL, &pSID, NULL);
VariantClear(&pSIDString);
VARIANT pSIDArray;
hr = pSID->Get(L"BinaryRepresentation", 0, &pSIDArray, NULL, NULL);
hr = pTrustee->Put(L"SID", 0, &pSIDArray, 0);
VariantClear(&pSIDArray);
VARIANT domain;
VariantInit(&domain);
V_VT(&domain) = VT_BSTR;
_bstr_t domainVal = _bstr_t(domainName);
V_BSTR(&domain) = domainVal;
hr = pTrustee->Put(L"Domain", 0, &domain, 0);
VariantClear(&domain);
VARIANT name;
VariantInit(&name);
V_VT(&name) = VT_BSTR;
_bstr_t nameVal = _bstr_t(accountName);
V_BSTR(&name) = nameVal;
hr = pTrustee->Put(L"Name", 0, &name, 0);
VariantClear(&name);
IWbemClassObject *pACEClass = NULL;
hr = pServices->GetObject(L"Win32_ACE", 0, NULL, &pACEClass, NULL);
IWbemClassObject *pACE = NULL;
hr = pACEClass->SpawnInstance(0, &pACE);
VARIANT accessMask;
V_VT(&accessMask) = VT_I4;
V_I4(&accessMask) = FILE_ALL_ACCESS; // Full Control
hr = pACE->Put(L"AccessMask", 0, &accessMask, 0);
VariantClear(&accessMask);
VARIANT aceFlags;
V_VT(&aceFlags) = VT_I4;
V_I4(&aceFlags) = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
hr = pACE->Put(L"AceFlags", 0, &aceFlags, 0);
VariantClear(&aceFlags);
VARIANT aceType;
V_VT(&aceType) = VT_I4;
V_I4(&aceType) = 0;
hr = pACE->Put(L"AceType", 0, &aceType, 0);
VariantClear(&aceType);
VARIANT trustee;
V_VT(&trustee) = VT_UNKNOWN;
V_UNKNOWN(&trustee) = (IUnknown *)pTrustee;
hr = pACE->Put(L"Trustee", 0, &trustee, 0);
VariantClear(&trustee);
return pACE;
I was able to figure out my problem. I realized that
SafeArrayPutElement returned an HRESULT and it told me immediately that
I was using a bad index which led me to a mis-specified lLbound. The
code I copied from MSDN for creating the array was assuming a 1-based
array index.
I now have solved all of my problems and am creating shares with the
permissions that I want!
if you have a lower bound of 0, it should just work
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound = 1; ////////////////////////////////////// change to
0
aDim[0].cElements = 2;
SAFEARRAY *daclACE = SafeArrayCreate(VT_UNKNOWN, 1, aDim);
--
I know have a great executable that will use WMI to create a share and
set the permissions that I want. It works perfectly when run from a
DOS shell. However, when run from a CreateProcess() call in an executable
running as a service, the pLocator->ConnectServer() calls fails with
0x800706a7 The RPC protocol sequence is not supported.
In wbemxprox.log, the error message is
ConnectViaDCOM, CoCreateInstanceEx resulted in hr = 0x0
(Tue Jul 09 13:56:25 2002) :
NTLMLogin resulted in hr = 0x800706a7(Tue Jul 09 13:56:25 2002) :
Error loading module {F7CE2E13-8C90-11D1-9E7B-00C04FC324A8},
return code is 0x800706a7(Tue Jul 09 13:56:25 2002) :
I thought this was a DLL loading issue, but I made sure that my PATH
includes C:\WINNT\system32\wbem .
Any ideas would be appreciated.
The environment in the process created from the service was empty. I
set the PATH to include
c:\winnt;c:\winnt\system32;c:\winnt\system32\wbem, but I didn't set
anything else.
Turns out that SystemRoot is required. By setting SystemRoot, everything
is working perfectly in the destination environment.