URLDownloadToCacheFile Problems - c++

--My first question here, please give me a hint If I do something wrong!
I'm using the URLDownloadToCacheFile function in different places of a software project I work for.
In the main UI is use this function to update a INI file from the Internet. Here I download the ini file directly with a URL. Works well.
In a DLL I use the same function to download a little binary file. This file has exact 308 bytes. It is an encrypted textfile with the ending ".db".
It's this second call that fails.
But this function do not fail on all computers, it just fail on a handfull of computers.
On my development computer it does not fail.
On some customer computers it does fail.
But just the one in the DLL. The call in the main GUI does not fail. Any idea? Or more information needed?
HRESULT hr = URLDownloadToCacheFile(
NULL, //ActiveX component calling this function
dbUrl, //Url to download
strFileName.GetBuffer(MAX_PATH), //pointer to a string containing the name of the downloade file
URLOSTRM_GETNEWESTVERSION, //size of filename buffer above
0, //reserved; must be zero
NULL); //optional IBindStatusCallback
if(SUCCEEDED(hr))
{
}

The problem occurs because you are trying to run the function on the same thread as the DLL creation. In this case use a different thread inside the dll to run the download function.

Related

Close shared files programmatically

The company I'm working with has a program written in ye olde vb6, which is updated pretty frequently, and most clients run the executable from a mapped network drive. This actually has surprisingly few issues, the biggest of which is automatic updates. Currently the updater program (written in c++) renames the existing exe, then downloads and places the new version into the old version's place. This generally works fine, but in some environments it simply fails.
The solution is running this command from microsoft:
for /f "skip=4 tokens=1" %a in ('net files') do net files %a /close
This command closes all network files that are shared (well... most) and then the updater can replace the exe.
In C++ I can use the System(""); function to run that command, or I could redirect the output of net files, and iterate through the results looking for the particular file in question and run net file /close command to close them. But it would be much much nicer if there were winapi functions that have similar capabilities for better reliability and future safety.
Is there any way for me to programmatically find all network shared files and close relevant ones?
You can programmatically do what net file /close does. Just include lmshare.h and link to Netapi32.dll. You have two functions to use: NetFileEnum to enumerate all open network files (on a given computer) and NetFileClose to close them.
Quick (it assumes program is running on same server and there are not too many open connections, see last paragraph) and dirty (no error checking) example:
FILE_INFO_2* pFiles = NULL;
DWORD nRead = 0, nTotal = 0;
NetFileEnum(
NULL, // servername, NULL means localhost
"c:\\directory\\path", // basepath, directory where VB6 program is
NULL, // username, searches for all users
2, // level, we just need resource ID
(LPBYTE*)&pFiles, // bufptr, need to use a double pointer to get the buffer
MAX_PREFERRED_LENGTH, // prefmaxlen, collect as much as possible
&nRead, // entriesread, number of entries stored in pFiles
&nTotal, // totalentries, ignore this
NULL //resume_handle, ignore this
);
for (int i=0; i < nRead; ++i)
NetFileClose(NULL, pFiles[i].fi2_id);
NetApiBufferFree(pFiles);
Refer to MSDN for details about NetFileEnum and NetFileClose. Note that NetFileEnum may return ERROR_MORE_DATA if more data is available.

Modify exe bytes at runtime to make file MD5 unique from last runtime

Each time I run the file I want the md5 to be unique without manually changing bytes in the compiler.
So how can I append some useless bytes to an .exe either on runtime or via another program?
Windows has a set of functions designed for this, the central one is UpdateResource.
MSDN also has an example: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648008(v=vs.85).aspx#_win32_Updating_Resources
However, you can't do this on a running program. You may put the code to scramble the resource content into a separate EXE, or a DLL spawned with RUNDLL32.exe.
Ok, this is how I solved it very easily.
Created a second program that runs this piece of code
char asd[100];
FILE* cfile = fopen("program.exe", "a");
fwrite(asd, 1, sizeof(asd), cfile);
fclose(cfile);
This successfully changes the MD5 of the program.

Trying to use URLRequestInfo::SetStreamToFile and URLResponseInfo::GetBodyAsFileRef

I am working on an NaCl plugin for Chrome, and trying to download a URL resource file locally, into the temporary cache of Chrome, but without success.
Here is how I proceed:
// I indicate that I want the resource to be downloaded to a file
m_URLRequestInfo.SetStreamToFile( true );
// I open the request:
m_URLLoader.Open( m_URLRequestInfo, m_CCFactory.NewCallback( &MyClass::OnOpen ) );
...
// My callback (OnOpen) is eventually called.
// I then check to make sure the status code is 200 using this call:
m_URLLoader.GetResponseInfo().GetStatusCode()
// Then I ask to download the whole file:
m_URLLoader.FinishStreamingToFile( m_CCFactory.NewOptionalCallback( &MyClass::OnFileDownloaded ) );
...
// My other callback (OnFileDownloaded) gets eventually called,
// and again the status code is 200.
// Then I query the FileRef using this call:
pp::FileRef l_FileRef = m_URLLoader.GetResponseInfo().GetBodyAsFileRef();
The returned pp::FileRef seems to be fine, but pp::FileRef::GetFileSystemType() returns PP_FILESYSTEMTYPE_EXTERNAL, and then the call to pp::FileRef::GetPath() fails (it returns an UNDEFINED pp::Var).
So from this point, I am lost. I don't know what else I should do to get a valid pp::FileRef that points to a local file in the browser's cache. My final goal is to open this local file (an image file in my case) using a standard system file IO like fopen().
Thanks for any light !
Is there a reason you can't use the nacl_io library instead? With it you can write something like this:
#include <stdio.h>
#include <sys/mount.h>
// Mount an HTTP filesystem that reads files from "http://example.com/path/...".
mount("http://example.com/path/", "/mnt/http", "httpfs", 0, "");
// Performs a URL Request of "http://example.com/path/my_image.png".
FILE* file = fopen("/mnt/http/my_image.png", "r");
...
Take a look a the nacl_io demo in the SDK. It is located at $NACL_SDK_ROOT/examples/demo/nacl_io.
After reading more thoroughly the documentation and running more tests, I finally figured out what I was doing wrong.
When we call pp::URLLoader::FinishStreamingToFile, then the file is downloaded in Browser's cache, but it cannot be opened/read using regular stdio services like fopen, fread etc. We need to use the pp::FileIO class services to open the obtained pp::FileRef and read the content of the file.
So here is what I did to successfully load and read a file that was downloaded for me by the Browser. Basically, I continued to use the C++ PPAPI services.
(1) upon callback from m_URLLoader->FinishStreamingToFile, we then call m_FileIO->Open to open the downloaded file using the obtained FileRef;
(2) upon callback from m_FileIO->Open, we then call m_FileIO->Query to obtain the size of the downloaded file (and some other file attributes);
(3) upon callback from pp::FileIO::Query, we then check the file attribute type (e.g. not a folder), allocate a memory buffer large enough to hold the whole file content, and start to call pp::FileIO::Read to obtain the file's content;
(4) upon callback from pp::FileIO::Read, if the obtained nResult argument is 0, then we reached the EOF and we finished reading the file content into our memory buffer; if the obtained nResult > 0, then it indicates the number of successfully read bytes, and we call m_FileIO->Read again to continue reading bytes, and storing them at a different offset location into our memory buffer; if the obtained nResult < 0 then an error occurred and we must terminate the reading process.
Many steps, and many callbacks to manage, but in the end this works smoothly.

Receiving a Sharing Violation Opening a File Code 32

I have been trying the following piece of code that does not work. What I am trying to do is to start executing my exe (one that I created a simple dialog based application using VC6.0) then from inside this application modify its own contents stored on the hard drive.
So there is a running copy of the exe and from this running copy it will open the disk copy into a buffer. Once loaded into a buffer then begin a search for a string. Once the string is found it will be replaced with another string which may not be the same size as the original.
Right now I am having an issue of not being able to open the file on disk for reading/writing. GetLastError returns the following error "ERROR_SHARING_VIOLATION The process cannot access the file because it is being used by another process.".
So what I did I renamed the file on disk to another name (essential same name except for the extension). Same error again about sharing violation. I am not sure why I am getting this sharing violation error code of 32. Any suggestions would be appreciated. I'll ask my second part of the question in another thread.
FILE * pFile;
pFile = fopen ("Test.exe","rb");
if (pFile != NULL)
{
// do something like search for a string
}
else
{
// fopen failed.
int value = GetLastError(); // returns 32
exit(1);
}
Read the Windows part of the File Locking wikipedia entry: you can't modify files that are currently executing.
You can rename and copy them, but you can't change them. So what you are trying to do is simply not possible. (Renaming the file doesn't unlock it at all, it's still the same file after the rename, so still not modifiable.)
You could copy your executable, modify that copy, then run that though.

Get a file's size through `IShellItem`

I've implemented a directory walking algorithm for the Windows Shell using IShellItem, IShellFolder, IStorage, IStream, etc. All is well and good. I can even walk inside shell namespace extensions (e.g. .zip) files.
However, I have problems extracting (regular) file sizes when files are being used by some other program with exclusive access.
AFAIK, there is nothing but the STATSTG structure that gives more information than the file's name. There are essentially 3 ways to get a hold of a STATSTG for a IShellItem:
Iterate using IEnumSTATSTG instead of IEnumIDList. Instead of invoking IShellFolder::EnumObjects(), get the IStorage for the folder and invoke IStorage::EnumElements(). You now get STATSTG structures directly.
Get the IStorage for the IShellItem and invoke IStorage::Stat().
Get the IStream for the IShellItem and invoke IStream::Stat().
I would really like to use #1 because it would give me all the information I need. However, I cannot get it to enumerate folder contents. I successfully extract the IStorage for the folder: it's own Stat() gives me the proper folder name. I successfully extract the IEnumSTATSTG, but the first call to Next(1, &item, NULL) returns S_FALSE and terminates the enumeration.
I would fallback to use #2 as it is still not so bad, but extracting the IStorage for regular disk files produces an error using both of IShellItem::BindToHandler(0, BHID_Storage, ...) and IShellFolder::BindToStorage(child, ...).
I finally tried #3 although it just plains seems wrong and it succeeds as long as files are not being used with exclusive access by another program.
I've googled around a bit and found several code snippets that use approach #3.
Question: Can anyone explain how I'm supposed to get the file's STATSTG without using approach #3?
Should approach #1 work, or does the IStorage implementation for regular folders simply not produce listings? Should approach #2 work or is the IStorage implementation simply not implemented for regular files?
Environment: Windows Vista Ultimate 32-bit, Visual Studio 2008 Express. Using C++, no ATL, all custom COM wrappers (in-house, may be suitably modified assuming somwthing is wrong there).
Have you tried getting hold of the IShellItem2 interface, and then querying for the value of the PKEY_Size property?
Even with the accepted answer, it took some doing.
The first thing you need is the Windows Properties reference. From there you have to know that you want to go into System.Size. From there you get the two important pieces of information:
System.Size
The system-provided file system size of the item, in bytes.
shellPKey = PKEY_Size
typeInfo
type = UInt64
Knowing that it's a UInt64, you can then get ahold of the IShellItem2 interface, in order to use one of the many property-getting methods:
//Get the IShellItem2 interface out of the IShellItem object
IShellItem2 si2 = shellItem as IShellItem2;
//Get the file fize (in bytes)
UInt64 fileSize;
si2.GetUInt64(PKEY_Size, ref fileSize);