I'm trying to open the MessageStore of a user using MAPI. The weird thing is, when I run this a console application, while I'm logged with the user, everything works fine.
But when I run this as a Windows Service I get MAPI_E_NOT_FOUND when trying to open the MessageStore.
I already configured the service to run as the user.
MapiLogonEx seems to work fine and GetMsgStoreTables also gives me the correct results (I verfied that the EntryID of the MessageStore is correct).
Here's my code:
LPMAPITABLE pStoresTbl = NULL;
m_lpMAPISession->GetMsgStoresTable(0, &pStoresTbl);
// Query Collumns
LPSPropTagArray pTags = NULL;
LPSRowSet pRows = NULL;
pStoresTbl->SeekRow(BOOKMARK_BEGINNING,0,NULL);
pStoresTbl->QueryRows(
LONG_MAX,
NULL,
&pRows);
LPSBinary lpEntryID = NULL;
ULONG iprops;
for (iprops = 0; iprops < pRows->aRow[0].cValues; iprops++)
{
SPropValue sProp = pRows->aRow[0].lpProps[iprops];
if (PROP_ID(sProp.ulPropTag) == PROP_ID(PR_ENTRYID))
{
lpEntryID = &sProp.Value.bin;
break;
}
}
lpMDB = NULL;
HRESULT hres = m_lpMAPISession->OpenMsgStore(NULL,
lpEntryID->cb,
(LPENTRYID) lpEntryID->lpb,
NULL,
MDB_NO_DIALOG |
MDB_NO_MAIL | // spooler not notified of our presence
MDB_TEMPORARY | // message store not added to MAPI profile
MAPI_BEST_ACCESS,
&lpMDB);
Is that an Exchange profile? Are you sure you are opening the primary mailbox rather than the PF store?
Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
Do you pass in the MAPI_NT_SERVICE flag in the MAPIINIT_0 structure when calling MAPIInitialize? I've never not passed it in when running in a service, so I'm not exactly sure what happens if you don't. The MSDN docs say it is required.
MAPI_NT_SERVICE
The caller is
running as a Windows service. Callers
that are not running as a Windows
service should not set this flag;
callers that are running as a service
must set this flag.
Related
I'm going a little crazy here. I am trying to read the value of a registry string value I manually created and every time it returns a null. If I try to read the value of an existing registry string value, it returns the value just fine. Here is the code I'm using:
ManagementBaseObject rinParams = registry.GetMethodParameters("GetStringValue");
rinParams["hDefKey"] = HKEY_LOCAL_MACHINE;
rinParams["sSubKeyName"] = #"SOFTWARE\Microsoft\.NetFramework";
// rinParams["sValueName"] = "InstallRoot";
rinParams["sValueName"] = "test";
ManagementBaseObject routParams = registry.InvokeMethod("GetStringValue", rinParams, null);
if (routParams.Properties["sValue"].Value != null)
{
routput = routParams.Properties["sValue"].Value.ToString();
}
What I did was set the code to use the above code to read the value of the "InstallRoot" in the registry HKEY_LOCAL_Machine\SOFTWARE\Microsoft.NetFramework\InstallRoot which is a REG_SZ value. I get a successful read and the directory path is returned just fine. I then created another REG_SZ variable name "test" in the same .NetFramework key and commented out the "sValueName" = "InstallRoot" and replaced it with a line for "sValueName" = "test". When I run this code under the debugger, I get a return value of null.
I've tried adding keys under SOFTWARE and values in that key like SOFTWARE\Testkey and I get the same result every time. It will not let me read a key I create, it always returns null, but it seems like I can read any key that already existed. I don't understand why I'm getting this result.
An FYI, is that I am doing a remote registry read from a Windows 7 PC. My ultimate goal is to be able to add registry keys and values. I've tried to do that and I always get an error exception "Not Found" when I try that, so I'm trying to get down to the easiest thing possible, which is to read a key and even that's not working. Any ideas for what might be going on here?
This is how I'm making the remote connection to the Windows 2008r2 server to read the registry:
ConnectionOptions connectoptions = new ConnectionOptions();
connectoptions.Impersonation = ImpersonationLevel.Impersonate;
connectoptions.Authentication = AuthenticationLevel.PacketPrivacy;
connectoptions.Username = "administrator";
connectoptions.Password = **password redacted**
ManagementScope scope = new ManagementScope(#"\\" + systemIP + #"\root\default");
scope.Options = connectoptions;
ManagementClass registry = new ManagementClass(scope, new ManagementPath("StdRegProv"), null);
I'm trying to locate a list item contained within the Services window (Start->Run->Services.msc) on Windows. The list item is named "Arc Service" and is easily found using Inspect, but my code fails to locate it. This being a relatively simple case, I feel I must be doing something wrong.
The code in question is:
VARIANT arcServiceNameVariant;
VariantInit(&arcServiceNameVariant);
arcServiceNameVariant.vt = VT_BSTR;
arcServiceNameVariant.bstrVal = L"Arc Service";
CComPtr<IUIAutomationCondition> arcServiceNameCondition;
hr = g_pAutomation->CreatePropertyCondition(UIA_NamePropertyId, arcServiceNameVariant, &arcServiceNameCondition.p);
if(SUCCEEDED(hr)) {
CComPtr<IUIAutomationElement> arcServiceElement;
hr = rootElement->FindFirst(TreeScope_Descendants, arcServiceNameCondition, &arcServiceElement.p);
if(SUCCEEDED(hr)) {
if(arcServiceElement.p) {
logInfo(L"Arc Service element found!");
}
} else {
logInfo(L"FindFirst failed!");
}
} else {
logInfo(L"Failed to create property condition!");
}
The "Arc Service element found!" branch is never entered.
Here are the details from Inspect describing the element:
Any assistance would be greatly appreciated. Thanks!
Quizzically it turns out that running my UIA client as Administrator sees the component, but running as the logged in user does not. For now I can elevate my process, but I'll continue to research the issue for a more detailed explanation.
I'm creating a user with the NetUserAdd API. It returns successfully, the user has a User folder and I can see the username with wmic useraccount get name. However, the created user is not visible under the control panel, nor on the logon screen. I assume that I need to add the user to some group but I don't know which or how.
Here is how I create the user:
USER_INFO_1 user_info;
ZeroMemory(&user_info, sizeof(user_info));
user_info.usri1_name = userName;
user_info.usri1_password = password;
user_info.usri1_priv = USER_PRIV_USER;
user_info.usri1_flags = UF_SCRIPT | UF_DONT_EXPIRE_PASSWD;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&user_info, &dwError);
How can I make the user visible on the logon screen?
You have created the user but you need to add it to the users group using NetLocalGroupAddMembers.
EDIT: Just realized I was providing the method for .NET. See this example for C++.
The user was not showing up on the welcome screen because it was not added to the Users group. This is how to do it:
LOCALGROUP_MEMBERS_INFO_3 lmi3;
ZeroMemory(&lmi3, sizeof lmi3);
lmi3.lgrmi3_domainandname = user_info.usri1_name;
DWORD err = NetLocalGroupAddMembers(NULL, L"Users", 3, (LPBYTE) &lmi3, 1);
First, here is a picture of what I see
http://img713.imageshack.us/img713/4797/iedrop.png
I need an solution to clear addressbar dropdawn, but not using ClearMyTracksByProcess or IE dialogs. I need to delete only a specific URL and all his traces.
I deleted manually all traces of that URL in:
Users\\AppData\Local\Microsoft\Windows\Temporary Internet Files*
Users\\AppData\Local\Microsoft\Windows\History*
Users\\Recent*
also that URL can be found in:
4) Users\\AppData\Local\Microsoft\Internet Explorer\Recovery\High
Now I made an BootTime program that searches for 8 and 16 bit charsets string in all my system disc files. URL wasn't found anywhere, but after logging and starting IE, the URL is still there. I suspect this is related to 4), but can't understand how.
Finally I found solution.
HRESULT CreateCatalogManager(ISearchCatalogManager **ppSearchCatalogManager)
{
*ppSearchCatalogManager = NULL;
ISearchManager *pSearchManager;
HRESULT hr = CoCreateInstance(CLSID_CSearchManager, NULL, CLSCTX_SERVER, IID_PPV_ARGS(&pSearchManager));
if (SUCCEEDED(hr))
{
hr = pSearchManager->GetCatalog(L"SystemIndex", ppSearchCatalogManager);
pSearchManager->Release();
}
return hr;
}
{
ISearchCatalogManager *pCatalogManager;
HRESULT hr = CreateCatalogManager(&pCatalogManager);
if (SUCCEEDED(hr))
{
pCatalogManager->Reset();
pCatalogManager->Release();
}
}
Address bar urls are stored in the TypedUrls registry key. See this project which claims to enum and delete them (I haven't tested it).
The History items in the dropdown are stored in the Url History database. Use IUrlHistoryStg::DeleteUrl().
I want to get the process's user name and check if it is a local administrator . Or check directly if the current procees user is a local administrator
Get the current username with GetUserName(), then call NetUserGetInfo() with the server name (NULL for local) and username you just got. Pass it a USER_INFO_1 structure, and then access usri1_priv in the structure. If the value is USER_PRIV_ADMIN, then you'll know that the username is an admin.
Tested on Windows XP SP3, Windows 7 32 bit and 64 bit with admin user and non-admin user.
Code ported from equivalent C# and uses ATL windows security wrapper classes.
#include <atlbase.h>
#include <atlsecurity.h>
// The function returns true if the user who is running the
// application is a member of the Administrators group,
// which does not necessarily mean the process has admin privileges.
bool IsAdministrator(HRESULT &rHr)
{
bool bIsAdmin = false;
try
{
// Open the access token of the current process.
ATL::CAccessToken aToken;
if (!aToken.GetProcessToken(TOKEN_QUERY))
{
throw MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32,
::GetLastError());
}
// Query for the access token's group information.
ATL::CTokenGroups groups;
if (!aToken.GetGroups(&groups))
{
throw MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32,
::GetLastError());
}
// Iterate through the access token's groups
// looking for a match against the builtin admins group.
ATL::CSid::CSidArray groupSids;
ATL::CAtlArray<DWORD> groupAttribs;
groups.GetSidsAndAttributes(&groupSids, &groupAttribs);
for (UINT i = 0; !bIsAdmin && i < groupSids.GetCount(); ++i)
{
bIsAdmin = groupSids.GetAt(i) == ATL::Sids::Admins();
}
rHr = S_OK;
}
catch (HRESULT hr)
{
rHr = hr;
}
return bIsAdmin;
}
Presuming you're on a Window OS there's a shell function: IsUserAnAdmin
See MSDN article
This article does suggest rolling your own function though, use CheckTokenMembership. There is even a code example to help you along.