Why isn't IUpdateSession::WebProxy working on Windows 10? - windows

I've got some in-house code that performs a Microsoft Update scan using the Windows Update API. Because some of the clients do not have direct internet access, I explicitly set the WebProxy property to point to our local proxy server. During testing (on Windows 7) this seemed to work perfectly. Now I'm testing it on Windows 10 (see footnote 1) and it seems that the proxy setting is being ignored.
The Windows Update client was revised significantly in Windows 10, so it is possible that this is a bug or undocumented limitation in the new version of the client, but on the other hand I have little previous experience using COM so I might be doing something wrong.
Observed results, using the test code posted below:
The code works as desired on Windows 7, regardless of what security context it is run in, and regardless of whether or not the client has direct internet access and/or a proxy server configured in the user's Internet settings.
The code also works on Windows 10, provided the client has direct internet access.
The code mostly works on Windows 10 if the client does not have direct internet access but the user that runs it has a suitable proxy server configured in their Internet settings. (See footnote 2.)
The code does not work on Windows 10 if the client does not have direct internet access and the user that runs it does not have a suitable proxy configured. Instead of connecting to the proxy specified in the code, it attempts to connect to a series of external IP addresses; once all of these connection attempts have finally timed out, it returns 0x80072ee2, ERROR_INTERNET_TIMEOUT, on the line shown. (I can get very similar behaviour on Windows 7 by leaving out the part of the code that sets the proxy server.)
Also, if I deliberately change the proxy URL in the code to point to a non-existent server, the code stops working on Windows 7, as expected, but the behaviour on Windows 10 is unchanged. So it really does look as though Windows Update is simply ignoring the WebProxy property. (The property is being set; I can read it back from the IUpdateSession object.)
Changing the Delivery Optimization Download Mode does not appear to help. I've tried all of the different modes that are available via Group Policy. Adding a trailing slash to the proxy URL broke the code for Windows 7 and made no difference for Windows 10. Using a bare DNS name rather than a URL worked on Windows 7 but made no difference on Windows 10.
Since the code is ultimately intended to become part of a system service and/or be run remotely, configuring proxy settings at the user level is not an ideal option, though I might be able to fall back on that if no other solution is available.
This is the code I've been testing, a cut-down version of the original code. The test code does not actually process the results, if any, since the problem occurs before that point. I've hidden the real DNS name of our proxy server, but the URL is of the form shown. Anyone wanting to test the code in their own environment will of course need to point it at their own proxy anyway.
#include <windows.h>
#include <wuapi.h>
#include <stdio.h>
#define stringize1(x) L#x
#define stringize(x) stringize1(x)
#define fail() fail_fn(L"Fatal error at line " stringize(__LINE__))
void fail_fn(wchar_t * msg)
{
wprintf(L"%s\n", msg);
exit(1);
}
int wmain(int argc, wchar_t ** argv)
{
IUpdateSearcher* updateSearcher;
IWebProxy* webProxy;
IUpdateServiceManager2* serviceManager;
IUpdateServiceRegistration* serviceRegistration;
IUpdateSession* updateSession;
ISearchResult* results;
BSTR searchString, proxyString, bstrServiceID;
HRESULT hr;
if((hr = CoInitialize(NULL)) != S_OK) {
fail();
}
hr = CoCreateInstance(&CLSID_UpdateServiceManager, NULL, CLSCTX_INPROC_SERVER,
&IID_IUpdateServiceManager2, (void **)&serviceManager);
if (hr != S_OK) fail();
bstrServiceID = SysAllocString(L"7971f918-a847-4430-9279-4a52d1efe18d");
serviceManager->lpVtbl->AddService2(serviceManager, bstrServiceID,
asfAllowPendingRegistration | asfRegisterServiceWithAU,
NULL, &serviceRegistration);
if (hr != S_OK) fail();
hr = CoCreateInstance(&CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER,
&IID_IUpdateSession, (LPVOID*)&updateSession);
if (hr != S_OK) fail();
hr = CoCreateInstance(&CLSID_WebProxy, NULL, CLSCTX_INPROC_SERVER,
&IID_IWebProxy, (void **)&webProxy);
if (hr != S_OK) fail();
hr = webProxy->lpVtbl->put_AutoDetect(webProxy, VARIANT_FALSE);
if (hr != S_OK) fail();
proxyString = SysAllocString(L"http://proxy.contoso.co.nz:80");
if (proxyString == NULL) fail();
hr = webProxy->lpVtbl->put_Address(webProxy, proxyString);
if (hr != S_OK) fail();
hr = updateSession->lpVtbl->put_WebProxy(updateSession, webProxy);
if (hr != S_OK) fail();
hr = updateSession->lpVtbl->CreateUpdateSearcher(updateSession, &updateSearcher);
if (hr != S_OK) fail();
hr = updateSearcher->lpVtbl->put_ServerSelection(updateSearcher, ssOthers);
if (hr != S_OK) fail();
hr = updateSearcher->lpVtbl->put_ServiceID(updateSearcher, bstrServiceID);
if (hr != S_OK) fail();
searchString = SysAllocString(L"IsInstalled=0 and Type='Software'");
hr = updateSearcher->lpVtbl->Search(updateSearcher, searchString, &results);
if (hr != S_OK) /* fails here */
{
wprintf(L"Error %0x\n", hr);
fail();
}
wprintf(L"Update search completed successfully.\n");
CoUninitialize();
exit(0);
}
Is there anything I can do to make this work on Windows 10 the same way as it does on Windows 7?
(1) I am running Windows 10 LTSB 2016. This is basically the same as Windows 10 version 1607, also known as Windows 10 Anniversary Update. Most of my clients don't have the March updates but are otherwise up to date. I've also confirmed that the problem still occurs on a client with the March updates installed.
(2) During testing, using the user-configured proxy has failed on two occasions, both on newly reinstalled machines; once it starts working, it keeps working. In this scenario, the scan does still attempt to connect to various external IP addresses, but the fact that these connections time out does not cause the scan to fail. I suspect this all has something to do with the Delivery Optimization download mode, but I'm still experimenting.
Addendum: the case where the user account the code is running as has a suitable proxy server configured in their Internet Settings only works when the code is run interactively. In a non-interactive context, e.g., a service or scheduled task, this does not work. At present, it appears to me to be impossible on a Windows 10 machine to access Microsoft Update from a service unless you have direct internet access.

Related

CreateFile returns Access_Denied in Win10

CreateFile() returns ACCESS_DENIED in Windows10 when i try in my project. If i create sample application using CreateFile() it works fine. Even tried to check admin privileges before calling CreateFile(), user is in admin mode. Same code works fine in Win 7.
Below is code sample:
WCHAR userPath[] = L"C:\\test.txt";
HANDLE hFile = NULL;
hFile = ::CreateFile(userPath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
wprintf(L"Error HANDLE = 0x%x \n",hFile);
}
else
{
wprintf(L"Suceess HANDLE = 0x%x \n",hFile);
::CloseHandle(hFile);
}
The most obvious explanation is that your user simply does not have sufficient rights to create files at the root level of the system drive.
Since Windows 7, and possibly even Vista, the default security configuration of the system drive permits standard user to create folders at the root level, but not files. So, my hypothesis is that you are not running your process elevated as you claim, but are in fact running the process with standard user rights. In order for you to create a file at that location you will need to either:
Run the process with elevated rights, or
Modify the security settings of the volume.
I was running my application in browser. There was issue with IE settings. When i disabled protected mode from IE->Security->Enable protected Mode, CreateFile() worked. Another solution is adding the ip to trusted site in IE.

Running EXE application in GINA beofe login screen (Command line)

I have created a Credential Launcher for Windows 7 and was able to run Windows application after the Tile button click event, it was very easy.
I added a few registry settings and *pbAutoLogon = FALSE;.
However now i am now trying to do the same for Windows XP.
Which function I should target or how to achieve the same results ?
I see you tagged your question with "Gina", so I guess you know that Credential Providers do not exist on XP.
Your answer depends on when exactly you want to run that program, especially with regards to the secure attention sequence (SAS, or when a user press CTRL-ALT-Delete)
Before the SAS, use WlxDisplaySASNotice
After the SAS, use WlxLoggedOutSAS
Since you don't want to write a whole GINA yourself, you could use a custom Gina that wraps msgina.dll. Here is one I wrote, you can find the original I started from in the Platform SDK.
Using that approch, you get a chance to execute code just before or just after certain events, like running your program after a successful logon, something like :
int WINAPI WlxLoggedOutSAS(PVOID pWlxContext, DWORD dwSasType, PLUID pAuthenticationId, PSID pLogonSid, PDWORD pdwOptions, PHANDLE phToken, PWLX_MPR_NOTIFY_INFO pMprNotifyInfo, PVOID * pProfile)
{
int result;
result = pfWlxLoggedOutSAS(pWlxContext, dwSasType, pAuthenticationId, pLogonSid, pdwOptions, phToken, pMprNotifyInfo, pProfile);
if (result == WLX_SAS_ACTION_LOGON)
{
//We have a successful logon, let's run our code
run_my_custom_code();
}
return result;
}
There are some caveats, though :
The code cannot block. Winlogon will wait, but your users might not. Spanw a process and let it run.
Your program will be running with SYSTEM privileges, which is a security risk. Sandboxing your process could be hard. If you can't break out of it, don't assume nobody can...

Camera not working on Windows Mobile 6.5

I have an application for Motorola MC9500 series that uses the device camera.
I use the following method to init the Imager:
Symbol.Generic.Device MyDevice;
int i = 0;
if (imager == null)
{
MyDevice = (Symbol.Generic.Device)Symbol.Imaging.Device.AvailableDevices.GetValue(0);
for (i = 1; MyDevice != null; i++)
{
if (MyDevice.FriendlyName.Equals("Image Capture Driver for Color Camera"))
break;
MyDevice = (Symbol.Generic.Device)Symbol.Imaging.Device.AvailableDevices.GetValue(i);
}
if (MyDevice == null)
{
MessageBox.Show("Camera não foi encontrada.");
this.Close();
return;
}
imager = new Symbol.Imaging.Imager(MyDevice);
}
It works fine on WM6.1 but not on WM6.5, where the last line throws the following exception:
Failed to create Imager: IMAGE_Open failed: E_IMG_INVALIDDEVICE
According to the manufacturer documentation, this means: "The physical device driver (PDD). DLL did not contain the required entry points.". However, I have all the drivers up-to-date. They can be found on: http://support.symbol.com/support/search.do?cmd=displayKC&docType=kc&externalId=12683&sliceId=&dialogID=469856149&stateId=1%200%20469852171
When I'm running the program, I have no other tasks running, since I thought this could be due to another process locking the camera to itself.
Relevant fact is that the camera doesn't seem to work/start in any other application that uses it. However, they seem to work on my client's device (also WM6.5, same device).
Anyone got any suggestion or idea of why this happens, or how to solve it?
I had the same problem, but mine was caused because I also had a Barcode scanner active, disabling the Barcode scanner fixed this for me.
barcode2.Disable()
You have to download and install a CAB to enable second source camera from motorola site (SPR23173).
I had this problem with a Motorola MC75A. Turns out it was the Datawedge application that was also installed on the device that was stopping it from working correctly. The camera and the barcode scanner appear to be kind of linked. You can only use one at once and as the DataWedge was already running, my code/project was producing the IMAGE_Open failed: E_IMG_INVALIDDEVICE. Simply going into DataWedge and stopping the process fixed this instantly.

OpenSSL WinINET client

I have a working client and a server which, once finished would have a valid SSL certificate.
At the moment, for the mean of testing, I'm just disabling the need of SSL verification in the client by adding the flags INTERNET_FLAG_IGNORE_CERT_CN_INVALID and SECURITY_FLAG_IGNORE_UNKNOWN_CA like this:
HINTERNET hRequest = HttpOpenRequest(hConnection,
"GET","index.html",
NULL,NULL,NULL,
INTERNET_FLAG_RELOAD|
INTERNET_FLAG_EXISTING_CONNECT
#ifdef __HTTPS__
| INTERNET_FLAG_SECURE |INTERNET_FLAG_IGNORE_CERT_CN_INVALID|SECURITY_FLAG_IGNORE_UNKNOWN_CA
#endif
,
dwContext);
I got this to work perfectly on my laptop. Now I'm trying to use it on my PC. same code exactly. copied and pasted the files (both Visual Studio Professional 2008), now I'm getting 12045 error. which means Invalid Certificate Authority
I tried disabling Windows Firewall, didn't work. both computer connected to the same router
Any ideas what can cause this?
Thanks!
EDIT
Basically what happens is the same as described here by Microsoft, only this article is for Windows CE
Does this help?
If a server SSL certificate is issued by unknown or invalid certificate authority WinInet HttpSendRequest API or MFC CInternetFile::SendRequest will fail with error 12045 (ERROR_INTERNET_INVALID_CA).
I think you should call InternetSetOption() on the request, before issuing it, like this, because the HttpOpenRequest() flags do not specify SECURITY_FLAG_IGNORE_UNKNOWN_CA:
HINTERNET hRequest = HttpOpenRequest(hConnection,...
#ifdef __HTTPS__
DWORD dwFlags;
DWORD dwBuffLen = sizeof(dwFlags);
InternetQueryOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&dwFlags, &dwBuffLen);
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
InternetSetOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags));
#endif
HttpSendRequest(hRequest,...

Terminal Services

HI,
Im using Delphi and I want to make an application that can do the following
When started from within Terminal services (remote desktop), if another user logs into another terminal services session they should be able to see the application running in the desktop tray. However if a user sitting at the server logs in then they shouldn't see the application running in the desktop tray. Its fine if everyone can see it running in the process list, just not the desktop tray.
How can I do this?
Make your application launch on startup on every user, then use this function to determine whether to quit or not:
#include <windows.h>
#include <winternl.h>
BOOL IsRunningOnTerminalServerClient( void )
{
PWINSTATIONQUERYINFORMATIONW WinStationQueryInformationW;
WINSTATIONINFORMATIONW wsInfo;
HINSTANCE hInstWinSta;
ULONG ReturnLen;
hInstWinSta = LoadLibraryA( "winsta.dll" );
if( hInstWinSta )
{
WinStationQueryInformationW = (PWINSTATIONQUERYINFORMATIONW)
GetProcAddress( hInstWinSta, "WinStationQueryInformationW" );
if( WinStationQueryInformationW &&
WinStationQueryInformationW( SERVERNAME_CURRENT,
LOGONID_CURRENT,
WinStationInformation,
&wsInfo,
sizeof(wsInfo),
&ReturnLen ) &&
( wsInfo.LogonId != 0 ) )
{
FreeLibrary( hInstWinSta );
return( TRUE );
}
FreeLibrary( hInstWinSta );
}
return FALSE;
}
Pulled from http://msdn.microsoft.com/en-us/library/aa383827(v=VS.85).aspx
Assumption: You are logging into a Windows Server - two people cannot RDP at the same time on the Desktop OSes. My experience with this is that you should not see applications running visually - ie on the desktop or on the taskbar or tray icon area.
If you go into the task manager and look at the processes running - you may see process running. Also, if you are Administrator, then you may "Kill" the process, else there is nothing you can do with it.
Does this help?
Please clarify what you are asking.

Resources