Failed to programmatically uninstall a font in Windows CE - c++

I would like to programmatically uninstall and delete 'simsun.ttc' font collection from '\Hard Disk\Fonts' on WinCE 5. I try to use RemoveFontResource() function but it fails and the last error is (0x2) (The system cannot find the file specified). I definitely know that the file is present.
...
BOOL res = RemoveFontResource(L"\\Hard Disk\\Fonts\\simsun.ttc");
DWORD err = GetLastError(); // 0x2
...
What is the problem?

Did you install the font, or did it come in the OS? If it came in the OS (which is likely) then you probably can't delete it. Why would you want to? Are you trying to save space? If so, get a new OS image without the font in it.

Related

Trying to understand process mitigation policies that can be set by SetProcessMitigationPolicy function

Sorry, if it's too broad of a question. I'm trying to see what exactly SetProcessMitigationPolicy function does in Windows 10, but I can't find much about it online (besides my previous forays into this subject.) I'm testing its PROCESS_MITIGATION_POLICY options one-by-one, and I have some questions about these:
ProcessSystemCallDisablePolicy states that it "Disables the ability to use NTUser/GDI functions at the lowest layer.". So I'm testing it as such:
PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY pmscdp = {0};
pmscdp.DisallowWin32kSystemCalls = 1;
BOOL bR = ::SetProcessMitigationPolicy(ProcessSystemCallDisablePolicy, &pmscdp, sizeof(pmscdp));
int err = ::GetLastError();
::GdiFlush(); //Try to trip it here
But it always fails with error code 19, or ERROR_WRITE_PROTECT.
So what exactly is it supposed to do and how do I set it?
ProcessExtensionPointDisablePolicy states that it "... prevents legacy extension point DLLs from being loaded into the process."
PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY pmepdp = {0};
pmepdp.DisableExtensionPoints = 1;
BOOL bR = ::SetProcessMitigationPolicy(ProcessExtensionPointDisablePolicy, &pmepdp, sizeof(pmepdp));
int err = ::GetLastError();
Sorry for my naivete, but what is the extension point DLL? And how can I test one?
ProcessSignaturePolicy states that it can "restrict image loading to those images that are either signed by Microsoft, by the Windows Store, or by Microsoft, the Windows Store and the Windows Hardware Quality Labs (WHQL)".
First off, it seems to have no effect on CreateProcess and only works with LoadLibrary-type functions. So if I do this:
PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY pmbsp = {0};
pmbsp.MicrosoftSignedOnly = 1;
//pmbsp.StoreSignedOnly = 1; //always seems to fail with this flag
//pmbsp.MitigationOptIn = 1; //Doesn't seem to have any effect
BOOL bR = ::SetProcessMitigationPolicy(ProcessSignaturePolicy, &pmbsp, sizeof(pmbsp));
BOOL err = ::GetLastError();
And then try to load some of my test DLLs:
HMODULE hModDll = ::LoadLibrary(L".\\Dll1.dll");
The LoadLibrary function fails with the MessageBox that reads:
Bad Image
Dll-Name is either not designed to run on Windows or it
contains an error. Try installing the program again using the original
installation media or contact your system administrator or the
software vendor for support. Error status 0xc0000428.
Interestingly, if I call it on some System32 DLL that is not signed:
HMODULE hModDll = ::LoadLibrary(L"iologmsg.dll");
it seems to work fine. But if I place a copy of my test Dll1.dll into System32 folder and load it this way:
HMODULE hModDll = ::LoadLibrary(L"Dll1_.dll");
it still fails with the same message box:
This is interesting. How can it tell the difference between iologmsg.dll and Dll1_.dll? Both files aren't signed.
PS. And that modal message box can throw in a really nasty wrench into the mix if the app (or the service) does not expect any UI to be shown there.
ProcessFontDisablePolicy lastly, I'm totally lost about this one. It states that it "turns off the ability of the process to load non-system fonts."
So after I enable it in my MFC GUI app:
PROCESS_MITIGATION_FONT_DISABLE_POLICY pmfdp = {0};
pmfdp.DisableNonSystemFonts = 1;
BOOL bR = ::SetProcessMitigationPolicy(ProcessFontDisablePolicy, &pmfdp, sizeof(pmfdp));
int err = ::GetLastError();
the app has a Richedit control that I can load a custom font in. So I went online and downloaded a totally random font. Then installed it in Windows Explorer and tried to use it from the app after that policy has been enabled:
//Set format for the text window
CHARFORMAT cf = { 0 };
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_FACE | CFM_SIZE;
cf.yHeight = 18 * 20;
VERIFY(SUCCEEDED(::StringCchCopy(cf.szFaceName, _countof(cf.szFaceName), L"Action Man")));
VERIFY(SetDefaultCharFormat(cf));
The app was able to display and use that (clearly non-system) font without any issues:
So what am I missing here in that policy?
This is guessing, but since many links in the function's documentation are 404s, I believe that the following would be valid:
1.Probably not implemented, yet.
2.Only a guess (since the link is also 404), but it might refer to DLLs used in obsolete situtations (like the XP and below login DLL, replaced in Vista with Credential Providers).
3.Windows DLLs are treated as signed (without actually having a digital signature attached), not only because they reside in System32, but because Windows keeps internally a map for them. For your DLLs, it won't work. Also, this has no point in CreateProcess() because the new process cannot interact with yours (without your knowledge) and, therefore, cannot hijack it, where a DLL loaded with LoadLibrary can do anything to ruin your process.
4.It probably refers to fonts not installed by Explorer, but fonts added with AddFontResource.

Unable to embed font using libHaru on Windows

I have following code that perfectly works on Linux:
auto pdf_doc = HPDF_New(nullptr, nullptr);
if (!pdf_doc) { /* error handling */ }
HPDF_SetCompressionMode(pdf_doc, HPDF_COMP_ALL);
HPDF_UseUTFEncodings(pdf_doc);
HPDF_SetCurrentEncoder(pdf_doc, "UTF-8");
const char* font_bold_name = HPDF_LoadTTFontFromFile(pdf_doc, "HelveticaBd.ttf", HPDF_TRUE);
auto font_bold = HPDF_GetFont(pdf_doc, font_bold_name, "UTF-8");
const char* font_regular_name = HPDF_LoadTTFontFromFile(pdf_doc, "Helvetica.ttf", HPDF_TRUE);
auto font_regular = HPDF_GetFont(pdf_doc, font_regular_name, "UTF-8");
But on Windows, call to HPDF_LoadTTFontFromFile() returns "" and error 105D is set in pdf_doc.
This error according to the documentation, means "Font cannot be embedded. (license restriction)".
But the same TTF font files are working on Linux. I also tried the font provided in demo but in that case it sets error 0x1017 in pdf_doc which means "Cannot open a file. (Detailed code is set.)"
Also the call succeeds when I pass HPDF_FALSE(meaning "do not embed the font") and it works. But I need to embed the font :(
Has anybody faced similar issue?
Am I missing something?
Why would license be an issue on Windows when Linux allows it?
Is it related to any font related settings/config on Windows?
Edit:
Error is occurring for Helvetica-bold font. The regular version of Helvetica doesn't cause any error but it is not getting embedded.
Does it have to do anything with the Base-14 fonts?

System Error 183 from print call (ERROR_ALREADY_EXISTS)

I am trying to get a test page printed from the Windows Driver Kit (WDK) 8.1 Samples (the bitmap sample). Since I did not get any print output, I placed a "GetLastError" call after each call to 'DrvWriteSpoolBuf":
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, (void*)&(pOemPDEV->bmFileHeader), sizeof(BITMAPFILEHEADER));
DWORD pdwReturn = GetLastError();
if (pdwReturn != ERROR_SUCCESS)
ERR("OEMEndDoc: Error printing=%ld\n", pdwReturn);
I received Error 183 !!! From System Error Codes:
ERROR_ALREADY_EXISTS
183 (0xB7)
Cannot create a file when that file already exists.
Alternate version of call above
DWORD res = pOemPDEV->pOEMHelp->DrvWriteSpoolBuf(pDevObj, &(pOemPDEV->bmFileHeader), sizeof(BITMAPFILEHEADER), &dwWritten);
I get res=E_FAIL
(apology for using bold - comments seem to overlook this result though)
How can I get such an error from printing ? (either to LPT1 or FILE: port)
I have tested the code by saving to a bitmap the exact contents I am trying to send to he spooler, the bitmap was created correctly.
...I apologize for not including more code, it is available at the link I posted above... Windows Driver Kit (WDK) 8.1 Samples
Windows Driver Kit (WDK) 8.1 Samples\OEM Printer Customization Plug-in Samples\C++\bitmap
It seems that, because of a function that was implemented and not disabled, there were two different methods to process image data... I was not aware that each sent their output to the spooler (generating the ERROR_ALREADY_EXISTS... is my guess)
(more precisely, while I did not implement FilterGraphics, but only ImageProcessing, I also should have returned S_FALSE for FilterGraphics in the GetImplementedMethod)

Moving Folder Windows C++: Works Vista and up, not XP

I've been working on getting this right for a few hours now, and it works perfectly on Windows Vista & Windows 7, but when I run it on Windows XP it fails without any message. Unfortunately I don't have a development environment under XP so I can't just run it through a debugger to check, have I missed something blindingly obvious? The same piece of code does actually use a CopyFile and a few commands to write out data to C:\ so if it's a permissions error it's an odd one.
EDIT: The return value is 1223, ERROR_CANCELLED which means cancelled by user.
EDIT 2: I disabled the s.fFlags and it immediately popped a dialog box up asking if it should create the dir-test folder, so I switched to FOF_NOCONFIRMATION and it appeared to ignore the flag. I do also use that during a deletion using the same SHFileOperation method so it either doesn't apply to file copies.
LPTSTR source = L"dir-test\\*\0";
LPTSTR dest = L"C:\\dir-test\0";
SHFILEOPSTRUCT s = { 0 };
s.hwnd = 0;
s.wFunc = FO_COPY;
s.fFlags = FOF_SILENT;
s.pTo = dest;
s.pFrom = source;
int n;
n = SHFileOperation(&s);`
So it turns out for some odd reason that using the SHFileOperation will force a confirm dialog for Windows XP (but not Vista or 7) and ignore the flags to tell it to just confirm. Simple fix of using CreateDirectory() prior to running the copy, which doesn't require a confirmation dialog.
The documentation for SHFILEOPSTRUCT has this warning:
It cannot be overstated that your paths should always be full paths. If the pFrom or pTo members are unqualified names, the current directories are taken from the global current drive and directory settings as managed by the GetCurrentDirectory and SetCurrentDirectory functions.
Your source specification is an unqualified name.

64 bit windows file opening

I'm trying to use a dialog box to open a file in my program. This works perfectly on a 32 bit system, but when I try to use it on 64 bit it is unable to open the file. I've figured out that if the file trying to be opened is in the same directory as my program, it works fine. Trying to open a file from another folder, however, doesn't work at all.
So, I tried to copy the file to the program folder. This also works fine on 32 bit but doesn't work at all on a 64 system. Any thoughts why?
char cwdl[500];
getcwd(cwdl,500);
string mystring = string(cwdl);
CFileDialog fileDlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, "All Files (*.*)|*.*||", this);
fileDlg.m_ofn.lpstrTitle = "Select New File";
if( fileDlg.DoModal() == IDOK)
{
CString newFile= fileDlg.GetFileName();
mystring+="\\"+newFile;
const char * newLoc = mystring.c_str();
CopyFile(newFile,newLoc,true);
this is just a snippet of the code.
UAC and file system redirection are related yet different.
User account control is a permissions based security to prevent unauthorized users from changing your file system or executing applications which may affect other users. The prompt allows you to override the security by providing administrator privileges temporarily if that was your intent.
File system redirection is to allow backwards compatibility with 32bit applications by having a mirrored 32bit system folders and registry. In fact if the action causes UAC to kick in redirection does not occur it will always try to use the 64bit version of the file in that case. Unless you specify the redirection directory explicitly or run the 32bit application with administrator privileges to bypass UAC.
Ok that said you are using a relative path so it will look for the file in the current directory for the process. If it's compiled as 32 bit process running it on systems with different architectures may not behave as expected due to aforementioned redirection.
You can use GetCurrentDirectory windows API to see what directory the current process is using and verify it is what you expected. If not you have a few options.
The easiest would be to use fully qualified file paths.
You could also have two builds one targeted for each architecture you intend to deploy on. After all if you're on a 64bit system you might as well deploy 64bit applications.
A more involved option would be to subclass CFileDialog and disable redirection by calling Wow64DisableWow64FsRedirection in the constructor and Wow64RevertWow64FsRedirection in the desctructor. However this is meant to be a system setting so you may get new problems by forcing your 32bit application on 64bit windows.
There are probably plenty of other options as well since there is usually many ways to skin a cat. However the first step is to put some debug code in place and verify or eliminate redirection as a culprit with GetCurrentDirectory
Maybe it's just me, but I'm seeing a strange result: in 64-bit mode, the first four bytes of the buffer used to store the location of the path, are filled with zeros.
char wk[_MAX_PATH];
char *ret = _getcwd(wk, _MAX_PATH); // wk = "\0\0\0\0C:\\MyFolder\\..."
// ret = "C:\\MyFolder\\..."
The return value OTOH is correct. "ret" points to wk + 4;
In 32-bit mode, there are no leading zeros, the path starts at the first byte. Note: this is a Multi-byte app, not Unicode.
I'm using Visual Studio 2010 (10.0.40219.1 SP1Rel).
Anyway, if you're getting the same result, that would explain why your example doesn't work. You would have to say (in 64-bit mode only):
string mystring = string(cwdl + 4); // 64-bit only
Weird or What?
Edit: Seems to be an alignment problem. Works OK if the _getcwd is in a separate function.