Windows-10 CreateFile2 error (ERROR_NOT_SUPPORTED_IN_APPCONTAINER) - windows

CreateFile2 api is returning ERROR_NOT_SUPPORTED_IN_APPCONTAINER when the file is not present/available in the path. My code is as below
CREATEFILE2_EXTENDED_PARAMETERS ms_param = {0};
ms_param.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
ms_param.dwFileAttributes = FILE_ATTRIBUTE_READONLY;
ms_param.dwFileFlags = FILE_FLAG_NO_BUFFERING;
ms_param.dwSecurityQosFlags = SECURITY_DELEGATION;
ms_param.lpSecurityAttributes = NULL;
ms_param.hTemplateFile = NULL;
g_hfile = CreateFile2(filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, OPEN_EXISTING, &ms_param);
if (g_hfile == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
I have already looked into this thread:CreateFile2 error in WinRT project (ERROR_NOT_SUPPORTED_IN_APPCONTAINER) , reporting similar issue. The solution suggested there doesnt work for me.
From this msdn page:CreateFile2 If the specified file or device does not exist, the function fails and the last-error code is set to ERROR_FILE_NOT_FOUND (2).But I am getting ERROR_NOT_SUPPORTED_IN_APPCONTAINER error

#Hans Passant's, comment helped me figure out the answer. Since I cannot upvote the comment I am adding it as an answer here:
CreateFile2 is not a way to bypass the sandbox restrictions. You only get access to the directories that the appxmanifest asks permissions for.
After checking his comment, I debugged my app deeper & was able to see that under certain scenarios, app was trying to read/write to files which were outside of accessible directories.

Related

Which handle should I use to initialize my scanner app

I wish to operate a scanner using a windows service hosting a web API.
The reason I am doing so is to be able to operate the scanner from javascript using ajax and I do not wish to use ActiveX.
So I built a Windows Service hosting a Web API.
I tried for the web API to start a scan application (had to bypass the UAC for this) but I run into a consistency issue (sometimes it worked and sometimes not).
So for now the controller of the web API has the code to start scanning built into it (instead of an external application). The problem is that I don`t have a handle to give the twain wrapper (it needs it for the windows message hook).
I tried to take the current process MainWindowHandle and even tried something silly as taking iexplore MainWindowHandle and I get an exception "Error initialising DSM".
As a twain library I use TwainDotNet
The code for doing is:
var p = Process.GetCurrentProcess();
_twain = new Twain(new WinFormsWindowMessageHook(p.MainWindowHandle));
Any idea on a good way to get a handle that will work? as I wrote above I ok with "stealing" another application handle if that will do the job (e.g. iexplore)
The exception is thrown from the TwainDotNet class DataSourceManager constructor in this code:
TwainResult result = Twain32Native.DsmParent(
ApplicationId,
IntPtr.Zero,
DataGroup.Control,
DataArgumentType.Parent,
Message.OpenDSM,
ref windowHandle);
if (result == TwainResult.Success)
{
...
}
else
{
throw new TwainException("Error initialising DSM: " + result, result);
}
Thanks
Well I found an answer to this one.
I used an ApplicationLoader class code from this URL.
The code I use to get the good handle is:
var processes = Process.GetProcessesByName("iexplore");
if (processes.Length == 0)
{
WriteToLog("ScanController.Run GetProcessesByName returned 0 processes. Something went wrong!!!");
return "ScanController.Run Failed: counlt not get handle to perform scan";
}
var p = processes[0];
var hProcess = ApplicationLoader.OpenProcess(ApplicationLoader.MAXIMUM_ALLOWED, false, (uint)p.Id);
Hope this will help someone.

DirectX Windows 8.1 fstream won't load file

I'm building a Windows 8.1 DirectX app and trying to load in an external to store level data.
The relevant code currently is (this method is called in the AssetHandler constructor):
void AssetHandler::LoadLevelsData()
{
unsigned int i = 0;
std::string lineData;
this->currentFile.open("Assets/reg.txt");
//Below statement here purely to check if the blasted thing is opening
if (this->currentFile.is_open())
{
i++;
}
while (std::getline(this->currentFile, lineData))
{
levels[i] = lineData;
i++;
}
currentFile.close();
}
The problem that i'm having is that the file does not appear to be opening. I have tried:
Using a full path
Opening the file in the initialisation list
A breakpoint shows that it is jumping over the if and while
I found some information saying that DirectX has constraints on working with external files but it did not specify exactly what these were.
The Item Type was set to 'Does not participate in build'. Setting this value to 'Text' solved the problem.

Obtaining admin privileges to delete files using rm from a Cocoa app

I am making a small app that deletes log files. I am using an NSTask instance which runs rm and srm (secure rm) to delete files.
I want to be able to delete files in:
/Library/Logs
~/Library/Logs
The issue is that the user account does not have permissions to access some files in the system library folder, such as the Adobe logs subfolder and others. For example, only the "system" user (group?) has r/w permissions for the Adobe logs folder and its contents, and the current user doesn't even have an entry in the permissions shown in the Get Info window for the folder.
What I want to be able to do exactly:
Obtain admin privileges.
Store the password in the Keychain so the app doesn't have to nag the user each time (Is the storage of the password a bad idea? Is it possible?)
Delete a file whatever the file permissions may be.
I am using NSTask because it offers notifications for task completion, getting text output from the task itself, etc. Would I need to use something else? If so, how could I replicate NSTask's completion notifications and output file handle while running rm and srm with admin privileges?
I am looking for the most secure way to handle the situation. i.e. I don't want my application to become a doorway for privilege escalation attacks.
I looked at the Authorization Services Programming Guide but I am not sure which case fits. At first I thought that AuthorizationExecuteWithPrivileges would be a good idea but after reading more on the subject it looks like this method is not recommended for security reasons.
A detailed answer would be very welcome. I'm sure some of you already had to do something similar and have some code and knowledge to share.
Thanks in advance!
Update:
I am now able to make the authentication dialog pop up and obtain privileges, like so:
OSStatus status;
AuthorizationRef authRef;
status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef);
AuthorizationRights authRights;
AuthorizationItem authItems[1];
authItems[0].name = kAuthorizationRightExecute;
authRights.count = sizeof(authItems) / sizeof(authItems[0]);
authRights.items = authItems;
AuthorizationFlags authFlags = kAuthorizationFlagDefaults | kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed;
status = AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, authFlags, NULL);
From the looks of it, it seems that the "Factored Application" method looks the most appropriate. The thing is that, to me, rm already seems like an external helper tool. I'm not sure I get the setuid alternative suggested in the documentation. Could I set the setuid bit on rm and run it using the NSTask method I already implemented? This would mean that I wouldn't need to create my own helper tool. Could somebody elaborate on this subject?
I also looked at the BetterAuthorizationSample which is suggested as a more secure and recent alternative to the setuid bit method, but found it awfully complex for such as simple behavior. Any hints?
Thanks in advance for any help!
Perhaps a tad late, but this might be useful for future reference for other people. Most of the code is from this person.
Basically, it has a lot to do with Authorization on the Mac. You can read more about that here and here.
The code, which uses the rm tool:
+ (BOOL)removeFileWithElevatedPrivilegesFromLocation:(NSString *)location
{
// Create authorization reference
OSStatus status;
AuthorizationRef authorizationRef;
// AuthorizationCreate and pass NULL as the initial
// AuthorizationRights set so that the AuthorizationRef gets created
// successfully, and then later call AuthorizationCopyRights to
// determine or extend the allowable rights.
// http://developer.apple.com/qa/qa2001/qa1172.html
status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
if (status != errAuthorizationSuccess)
{
NSLog(#"Error Creating Initial Authorization: %d", status);
return NO;
}
// kAuthorizationRightExecute == "system.privilege.admin"
AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0};
AuthorizationRights rights = {1, &right};
AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;
// Call AuthorizationCopyRights to determine or extend the allowable rights.
status = AuthorizationCopyRights(authorizationRef, &rights, NULL, flags, NULL);
if (status != errAuthorizationSuccess)
{
NSLog(#"Copy Rights Unsuccessful: %d", status);
return NO;
}
// use rm tool with -rf
char *tool = "/bin/rm";
char *args[] = {"-rf", (char *)[location UTF8String], NULL};
FILE *pipe = NULL;
status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe);
if (status != errAuthorizationSuccess)
{
NSLog(#"Error: %d", status);
return NO;
}
// The only way to guarantee that a credential acquired when you
// request a right is not shared with other authorization instances is
// to destroy the credential. To do so, call the AuthorizationFree
// function with the flag kAuthorizationFlagDestroyRights.
// http://developer.apple.com/documentation/Security/Conceptual/authorization_concepts/02authconcepts/chapter_2_section_7.html
status = AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights);
return YES;
}
I had this headache a few months ago. I was trying to get a shell script running with admin privileges that shutdown my computer at a certain time. I feel your pain.
I used the BetterAuthorizationSample which was a total nightmare to wade through. But I took the most pragmatic route - I didn't bother trying to understand everything that was going on, I just grabbed the guts of the code.
It didn't take me that long to get it doing what I wanted. I can't remember exactly what I altered, but you're welcome to check out my code:
http://github.com/johngallagher/TurnItOff
I hope this helps on your quest for a secure application!

How can I pre-authorize authopen?

I'm using authopen inside one of my programs to modify files owned by root. As can be seen in the screenshot below authopen asks for a admin password. What I'd like to achieve is that the dialog shows my app's name and then passes the authorization to authopen.
Code
Launching authopen which returns an authorized file descriptor.
int pipe[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, pipe);
if (fork() == 0) { // child
// close parent's pipe
close(pipe[0]);
dup2(pipe[1], STDOUT_FILENO);
const char *authopenPath = "/usr/libexec/authopen";
execl(authopenPath,
authopenPath,
"-stdoutpipe",
[self.device.devicePath fileSystemRepresentation],
NULL);
NSLog(#"Fatal error, we should never reach %s:%d", __FILE__, __LINE__);
exit(-1);
} else { // parent
close(pipe[1]);
}
// get file descriptor through sockets
I'd really like not to use AuthorizationExecuteWithPrivileges because then I'd have to get more rights than I want to.
Apple has added an option to authopen in OS X 10.9 Mavericks that allows exactly this. Prior this seemed to be impossible.
-extauth
specifies that authopen should read one AuthorizationExternalForm structure from stdin,
convert it to an AuthorizationRef, and attempt to use it to authorize the open(2)
operation.
The authorization should refer to the sys.openfile right corresponding to the requested operation.
The authorization data will be read before any additional data supplied on stdin, and will
not be included in data written with -w.
I have not used this yet, so I do not have any sample code. If someone has, please add it to this answer.
I think if you give your app path in the 1st arg:
execl(authopenPath,
"app path", // <--
"-stdoutpipe",
[self.device.devicePath fileSystemRepresentation],
NULL);
the dialog will show:
"app namerequires that you type your password"
You need to be looking directly at the security framework, introduced in 10.4, I think, and been the main authorization source since 10.5. OSX still works within PAM (like Linux), but /etc/authorization now supersedes this. Apple does have one or two samples of code on how you could pragmatically create a class/entry for someone to authorize themselves against (or preauthorize/be preauthorized like folks who are allowed to print).
This question is old but it seems to be possible, as explained in this technical note :
Technical Note TN2095 : Authorization for Everyone
http://developer.apple.com/library/mac/#technotes/tn2095/_index.html

DSOFramer closing Excel doc in another window. If unsaved data in file, dsoframer fails to open with "Attempt to access invalid address"

I'm using Microsoft's DSOFramer control to allow me to embed an Excel file in my dialog so the user can choose his sheet, then select his range of cells; it's used with an import button on my dialog.
The problem is that when I call the DSOFramer's OPEN function, if I have Excel open in another window, it closes the Excel document (but leaves Excel running). If the document it tries to close has unsaved data, I get a dialog boxclosing Excel doc in another window. If unsaved data in file, dsoframer fails to open with a messagebox: Attempt to access invalid address.
I built the source, and stepped through, and its making a call in its CDsoDocObject::CreateFromFile function, calling BindToObject on an object of class IMoniker. The HR is 0x8001010a The message filter indicated that the application is busy. On that failure, it tries to InstantiateDocObjectServer by classid of CLSID Microsoft Excel Worksheet... this fails with an HRESULT of 0x80040154 Class not registered. The InstantiateDocObjectServer just calls CoCreateInstance on the classid, first with CLSCTX_LOCAL_SERVER, then (if that fails) with CLSCTX_INPROC_SERVER.
I know DSOFramer is a popular sample project for embedding Office apps in various dialog and forms. I'm hoping someone else has had this problem and might have some insight on how I can solve this. I really don't want it to close any other open Excel documents, and I really don't want it to error-out if it can't close the document due to unsaved data.
Update 1: I've tried changing the classid that's passed in to Excel.Application (I know that class will resolve), but that didn't work. In CDsoDocObject, it tries to open key HKEY_CLASSES_ROOT\CLSID\{00024500-0000-0000-C000-000000000046}\DocObject, but fails. I've visually confirmed that the key is not present in my registry; The key is present for the guide, but there's no DocObject subkey. It then produces an error message box: The associated COM server does not support ActiveX document embedding. I get similar (different key, of course) results when I try to use the Excel.Workbook programid.
Update 2: I tried starting a 2nd instance of Excel, hoping that my automation would bind to it (being the most recently invoked) instead of the problem Excel instance, but it didn't seem to do that. Results were the same. My problem seems to have boiled down to this: I'm calling the BindToObject on an object of class IMoniker, and receiving 0x8001010A (RPC_E_SERVERCALL_RETRYLATER) The message filter indicated that the application is busy. I've tried playing with the flags passed to the BindToObject (via the SetBindOptions), but nothing seems to make any difference.
Update 3: It first tries to bind using an IMoniker class. If that fails, it calls CoCreateInstance for the clsid as a fallback method. This may work for other MS Office objects, but when it's Excel, the class is for the Worksheet. I modified the sample to CoCreateInstance _Application, then got the workbooks, then called the Workbooks::Open for the target file, which returns a Worksheet object. I then returned that pointer and merged back with the original sample code path. All working now.
#Jinjin
You can use the #import directive to import your Excel's OLB file. this should generate (and automatically include an Excel .tlh file which contains the structures for _Application (and the rest you need)). Ideally, you should find an OLB file that matches the earliest Excel version that you wish to support. The one on your local system is probably in c:\Program Files\Microsoft Office\Office12 (presuming you have Office 2007 installed). It may be named Excel.olb, or XL5EN32.OLB (different, obviously if you haven't installed the US English verion of Excel.
So, copy the .olb file to your project source directory, then at the top of the source file, add a line for #import "XL5EN32.olb".
Yes, opens older versions. Best way to guarantee that this will be the case is to find an OLB file (mentioned in item 1 above) that is from an installation of Excel that is the earliest version you wish to support. I use an Excel9.olb from Office 2000. Works fine with my testing of Excel versions all the way to the latest from Office 2007.
Yes, you should use dsoframer normally after making these changes.
I'm afraid I probably can't do that due to restrictions of my employer. However, if you take the "stock" dsoframer project, make the changes described in part 1 of this post, and the changes I described in my earlier post, you have pretty much recreated exactly what I have.
#Jinjin: did you put the import statement (#import "XL5EN32.olb") in the cpp file where you are using the Excel::_Application? If not, do that... can't just add it to the project. If you have already done that, try also adding this statement to the cpp file where you are using those mappings #import "Debug\XL5EN32.tlh". The tlh file is a header that is generated by running the #import; you should find it in your Debug directory (presuming you're performing a Debug build).
Renaming _Application to Application (and the others) is not the right way to go. The _Application structure is the one that has the mappings. That is why you are not finding the app->get_Workbooks.
What file are you looking in that you are finding Application but not _Application?
Assuming you are using the DSOFRAMER project, you need to add this code to dsofdocobj.cpp in the CreateFromFile function, at around line 348:
CLSID clsidExcelWS;
hr = CLSIDFromProgID(OLESTR("Excel.Sheet"),clsidExcelWS);
if (FAILED(hr)) return hr;
if (clsid == clsidExcelWS)
{
hr = InstantiateAndLoadExcel(pwszFile, &pole);
if (FAILED(hr)) return hr;
}
else
{
<the IMoniker::BindToObject call and it's failure handling from the "stock" sample goes here>
}
Then, define the following new member function in CDsoDocObject:
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::InstantiateAndLoadExcel (protected)
//
// Create an instance of Excel and load the target file into its worksheet
//
STDMETHODIMP CDsoDocObject::InstantiateAndLoadExcel(LPWSTR pwszFile, IOleObject **ppole)
{
IUnknown *punkApp=NULL;
Excel::_Application *app=NULL;
Excel::Workbooks *wbList=NULL;
Excel::_Workbook *wb;
CLSID clsidExcel;
HRESULT hr = CLSIDFromProgID(OLESTR("Excel.Application"), &clsidExcel);
if (FAILED(hr))
return hr;
hr = CoCreateInstance(clsidExcel, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&punkApp);
if (SUCCEEDED(hr))
{
hr = punkApp->QueryInterface(__uuidof(Excel::_Application),(LPVOID *)&app);
if (SUCCEEDED(hr))
{
hr = app->get_Workbooks(&wbList);
VARIANT vNoParam;
VariantInit(&vNoParam);
V_VT(&vNoParam) = VT_ERROR;
V_ERROR(&vNoParam) = DISP_E_PARAMNOTFOUND;
VARIANT vReadOnly;
VariantInit(&vReadOnly);
V_VT(&vReadOnly) = VT_BOOL;
V_BOOL(&vReadOnly) = VARIANT_TRUE;
BSTR bstrFilename = SysAllocString(pwszFile);
hr = wbList->Open(bstrFilename, vNoParam,vNoParam,vNoParam,vNoParam,vReadOnly,vNoParam,vNoParam,vNoParam,vNoParam,vNoParam,vNoParam,vNoParam,0,&wb);
if (SUCCEEDED(hr))
hr = wb->QueryInterface(IID_IOleObject, (void**)ppole);
VariantClear(&vReadOnly);
VariantClear(&vNoParam);
SysFreeString(bstrFilename);
}
}
if (wb != NULL) wb->Release();
if (wbList != NULL) wbList->Release();
if (app != NULL) app->Release();
if (punkApp != NULL) punkApp->Release();
return hr;
}

Resources