C++: Deleting a printer queue - c++

I'm trying to remove all the files in queue from a printer. I found this piece of code which seemed pretty straight forward.
I tried deleting the queue with the code below. It compiles, but SetPrinter returns false. The error message I got was 5, which I tried to decode to a "normal" error message using the approach from this question. But I wasn't able to compile with that, because STR_ELEMS is undefined. Searched google for "STR_ELEMS is undefined" but hit a dead end.
Can someone help me decode the error message and delete the printer queue?
BOOL bStatus = false;
HANDLE hPrinter = NULL;
DOC_INFO_1 DocInfo;
bStatus = OpenPrinter((LPTSTR)_T("CN551A"), &hPrinter, NULL);
if(bStatus) {
DWORD dwBufsize=0;
GetPrinterA(hPrinter, 2, NULL, 0, &dwBufsize); // Edit: Returns false
PRINTER_INFO_2* pinfo = (PRINTER_INFO_2*)malloc(dwBufsize);
long result = GetPrinterA(hPrinter, 2,
(LPBYTE)pinfo, dwBufsize, &dwBufsize);
if ( pinfo->cJobs==0 ) // Edit: pinfo->cJobs is not 0
{
printf("No printer jobs found.");
}
else
{
if ( SetPrinter(hPrinter, 0, 0, PRINTER_CONTROL_PURGE)==0 )
printf("SetPrinter call failed: %x\n", GetLastError() );
else printf("Number of printer jobs deleted: %u\n",
pinfo->cJobs);
}
ClosePrinter( hPrinter );
}
My includes are:
#include <windows.h>
#include <winspool.h>

The error code of 5 means "access is denied". (System Error Codes)
Try running with admin privileges.
To format a printable error message from the return value of GetLastError, use FormatMessage something like this:
TCHAR buffer[256];
if (0 == FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,
GetLastError(), 0, buffer, 256, 0)) {
// FormatMessage failed.
}
Also, you can try passing a PRINTER_DEFAULTS struct to OpenPrinter, maybe like this:
PRINTER_DEFAULTS PrnDefs;
PrnDefs.pDataType = "RAW";
PrnDefs.pDevMode = 0;
PrnDefs.DesiredAccess = PRINTER_ALL_ACCESS;
bStatus = OpenPrinter((LPTSTR)_T("CN551A"), &hPrinter, &PrnDefs);

Related

How to access the file pointer of each blocks of a file from the $MFT file in NTFS?

I am working on file virtualization and versioning project. For that, I need to access the logical blocks of file contents directly without copying into memory. Anyone could you help me with code snippets that works on my 64 bit windows?
I tried the following code to access the MFT file. But it responds like 'Access denied' even though I ran with administrator privileges.
#include<windows.h>
#include<stdio.h>
#include<winioctl.h>
// Format the Win32 system error code to string
void ErrorMessage(DWORD dwCode);
int wmain(int argc, WCHAR **argv){
HANDLE hVolume;
WCHAR lpDrive[] = L"\\\\.\\C:";
PNTFS_VOLUME_DATA_BUFFER ntfsVolData = {0};
BOOL bDioControl = FALSE;
DWORD dwWritten = 0;
hVolume = CreateFile(lpDrive, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if(hVolume == INVALID_HANDLE_VALUE){
wprintf(L"CreateFile() failed!\n");
ErrorMessage(GetLastError());
if(CloseHandle(hVolume) != 0)
wprintf(L"hVolume handle was closed successfully!\n");
else{
wprintf(L"Failed to close hVolume handle!\n");
ErrorMessage(GetLastError());
}
}
else
wprintf(L"CreateFile() is pretty fine!\n");
ntfsVolData = (PNTFS_VOLUME_DATA_BUFFER)malloc(sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA));
bDioControl = DeviceIoControl(hVolume, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, ntfsVolData,sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA), &dwWritten, NULL);
if(bDioControl == 0){
wprintf(L"DeviceIoControl() failed!\n");
ErrorMessage(GetLastError());
if(CloseHandle(hVolume) != 0)
wprintf(L"hVolume handle was closed successfully!\n");
else{
wprintf(L"Failed to close hVolume handle!\n");
ErrorMessage(GetLastError());
}
}
getchar();
}
void ErrorMessage(DWORD dwCode){
DWORD dwErrCode = dwCode;
DWORD dwNumChar;
LPWSTR szErrString = NULL; // will be allocated and filled by FormatMessage
dwNumChar = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM, 0, dwErrCode, 0, (LPWSTR)&szErrString, 0,0 ); // since getting message from system tables
if(dwNumChar == 0)wprintf(L"FormatMessage() failed, error %u\n", GetLastError());//else//wprintf(L"FormatMessage() should be fine!\n");
wprintf(L"Error code %u:\n %s\n", dwErrCode, szErrString) ;// This buffer used by FormatMessage()
if(LocalFree(szErrString) != NULL)
wprintf(L"Failed to free up the buffer, error %u\n", GetLastError());//else//wprintf(L"Buffer has been freed\n");
}
CreateFile() failed!
Error code 5:
Access is denied.
hVolume handle was closed successfully!
DeviceIoControl() failed!
Error code 6:
The handle is invalid.
hVolume handle was closed successfully!
Thank you
Admin privileges aren't enough. What you need to do is request backup and restore privileges for your process. MSDN has sample code. Keep in mind that you probably need both SE_BACKUP_NAME and SE_RESTORE_NAME.
The process is a bit cumbersome:
Use OpenProcessToken on your process with TOKEN_ADJUST_PRIVILEGES
Use LookupPrivilegeValue to get the privilege based on the string constants (one for SE_BACKUP_NAME, one for SE_RESTORE_NAME)
Use AdjustTokenPrivileges to acquire the backup and restore privileges
If you do this properly, the rest of your code should work. To actually enumerate the MFT, you'll want to use the FSCTL_ENUM_USN_DATA variant of DeviceIOControl.

Cannot read pipe from CreateProcess() thread

I'm stuck on this since days, i'm goind crazy.
Basically i'm trying to open cmd.exe in a thread and give it input and read output from it, from the parent. Like, assigning a tty in linux, since there's no such thing in windows. I have a good understanding of linux systems but can't say the same thing about windows.
So, here's "my" code:
#undef UNICODE
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
//using namespace std;
#define BUFFER_SIZE 99
// handles for cmd thread pipes
HANDLE cmd_in_rd = NULL;
HANDLE cmd_in_wr = NULL;
HANDLE cmd_out_rd = NULL;
HANDLE cmd_out_wr = NULL;
HANDLE cmd_thread_handle;
void PrintError(char *text, int err) {
DWORD retSize;
LPTSTR pTemp = NULL;
if (!err) return;
retSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
err,
LANG_NEUTRAL,
(LPTSTR)&pTemp,
0,
NULL);
if (pTemp) printf("%s: %s\n", text, pTemp);
LocalFree((HLOCAL)pTemp);
return;
}
int pipewrite(char *command) {
DWORD dwRead, dwWritten;
BOOL bSuccess = FALSE;
SetLastError(0);
WriteFile(cmd_in_wr, command, strlen(command), &dwWritten, NULL);
bSuccess = GetLastError();
PrintError("WriteToPipe", bSuccess);
return (bSuccess == 0) || (bSuccess == ERROR_IO_PENDING);
}
int __stdcall cmd_thread(int arg) {
// this function only prints when data is ready
DWORD dwRead, dwWritten;
CHAR chBuf[BUFFER_SIZE];
BOOL bSuccess = FALSE;
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
int rf_ret, wf_ret;
//CloseHandle(cmd_out_wr); makes readfile fail!!
SetLastError(0);
while (1) { // only executes once!!!!!!!
(rf_ret = ReadFile(cmd_out_rd, chBuf, BUFFER_SIZE, &dwRead, NULL))
&&
(wf_ret = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL));
printf("ReadFile returned: %d\nWriteFile returned: %d\n", rf_ret, wf_ret);
bSuccess = GetLastError();
PrintError("ReadingFromPipe", bSuccess);
}
bSuccess = GetLastError();
return (bSuccess == 0) || (bSuccess == ERROR_IO_PENDING);
}
int main(void) {
char buffer[BUFFER_SIZE];
// init the pipes
SECURITY_ATTRIBUTES cmd_sa;
cmd_sa.nLength = sizeof(SECURITY_ATTRIBUTES);
cmd_sa.bInheritHandle = TRUE;
cmd_sa.lpSecurityDescriptor = NULL;
if (!CreatePipe(&cmd_out_rd, &cmd_out_wr, &cmd_sa, 0)) {
printf("%s\n", "Error creating pipes");
return 1;
}
if (!SetHandleInformation(cmd_out_rd, HANDLE_FLAG_INHERIT, 0)) {
printf("%s\n", "Error setting handle infos");
return 1;
}
if (!CreatePipe(&cmd_in_rd, &cmd_in_wr, &cmd_sa, 0)) {
printf("%s\n", "Error creating pipes");
return 1;
}
if (!SetHandleInformation(cmd_in_rd, HANDLE_FLAG_INHERIT, 0)) {
printf("%s\n", "Error setting handle infos");
return 1;
}
// create the cmd thread
PROCESS_INFORMATION cmd_pi;
STARTUPINFO cmd_si;
ZeroMemory(&cmd_pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&cmd_si, sizeof(STARTUPINFO));
cmd_si.cb = sizeof(STARTUPINFO);
cmd_si.hStdError = cmd_out_wr;
cmd_si.hStdOutput = cmd_out_wr;
cmd_si.hStdInput = cmd_in_rd;
cmd_si.dwFlags |= STARTF_USESTDHANDLES;
TCHAR comm[] = TEXT("cmd.exe");
BOOL th = CreateProcess(NULL,
comm,
NULL,
NULL,
TRUE, // handles are inherited
0,
NULL,
NULL,
&cmd_si,
&cmd_pi);
if (th) {
CloseHandle(cmd_pi.hProcess);
CloseHandle(cmd_pi.hThread);
}
cmd_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)cmd_thread, NULL, 0, NULL);
// read commands from shell and send them to cmd
ZeroMemory(&buffer, BUFFER_SIZE);
while (1) {
fgets(buffer, BUFFER_SIZE, stdin);
if (!pipewrite(buffer)) break;
}
printf("Program terminated\n");
return 0;
}
I actually, for testing purposes, copied a lot from another question on stackoverflow and from MSDN since i couldn't get it to work on my main program. The things I don't understand are:
Why the while loop inside cmd_thread gets executed at startup and then hangs there waiting for the end of the world? I tried to close the pipe out_write handle from the parent before reading, but that makes other parts not working.
pipewrite() seems to work, but I can't be sure that the cmd.exe thread receives and works the input... Since i get no output :/
I thought about stracing/ltracing the program or running it into a debugger, but I know no tool for that...
The strange thing is that the original works (the one from where i got the code). I tried to spot the difference between the two, but even when I look to them side by side, they seem to do the exact same things.
The child process is dying as soon as it attempts to read from standard input, because:
if (!SetHandleInformation(cmd_in_rd, HANDLE_FLAG_INHERIT, 0)) {
This should have been:
if (!SetHandleInformation(cmd_in_wr, HANDLE_FLAG_INHERIT, 0)) {
like in the original code.
Also, your error handling is largely incorrect; you don't consistently check for errors and you sometimes call GetLastError() when no error has occurred. (Those problems are in the original code too.)
You also need to put the call to CloseHandle(cmd_out_wr); back in because otherwise you won't be able to tell when the child exits.
Oh, and incidentally, cmd.exe is a process, not a thread.

DeviceIoControl for SCSI INQUIRY command returns error 50

I am trying to access a USB scanner through the IOCTL commands. This is on Windows 7. I did not deal with IOCTL coding before, so I first tried the following snippet based on what I could find with a quick search.
#include "stdafx.h"
#include <stddef.h>
#include <Windows.h>
#include <ntddscsi.h>
#include <usbscan.h>
typedef struct
{
SCSI_PASS_THROUGH spt;
BYTE sense[18];
BYTE data[36];
} SPTSD;
LPTSTR ErrorMessage(DWORD error)
{
LPTSTR errorText = NULL;
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&errorText,
0,
NULL);
return errorText;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE h = CreateFile(L"\\\\.\\Usbscan0", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != h)
{
SPTSD sptsd={0};
sptsd.spt.Length = sizeof (sptsd.spt);
sptsd.spt.SenseInfoLength = sizeof(sptsd.sense);
sptsd.spt.DataTransferLength = sizeof(sptsd.data);
sptsd.spt.SenseInfoOffset = offsetof (SPTSD, sense);
sptsd.spt.DataBufferOffset = offsetof (SPTSD, data);
sptsd.spt.TimeOutValue = 30;
sptsd.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptsd.spt.CdbLength = 6;
sptsd.spt.Cdb[0] = 0x12; // SCSI INQUIRY command
sptsd.spt.Cdb[1] = 0;
sptsd.spt.Cdb[2] = 0;
sptsd.spt.Cdb[3] = 0;
sptsd.spt.Cdb[4] = sizeof(sptsd.data);
sptsd.spt.Cdb[5] = 0;
DWORD dwReturnedBytes;
BOOL b;
b = DeviceIoControl(h, IOCTL_SCSI_PASS_THROUGH, &sptsd, sizeof(sptsd), &sptsd, sizeof(sptsd), &dwReturnedBytes, NULL);
if (b == 0)
{
LPTSTR errortext = ErrorMessage(GetLastError());
wprintf(L"DeviceIoControl(IOCTL_SCSI_PASS_THROUGH-INQUIRY) failed with error %d : %s\r\n", GetLastError(), errortext);
LocalFree(errortext);
}
else
{
wprintf(L"DeviceIoControl(IOCTL_SCSI_PASS_THROUGH-INQUIRY) succeeded\r\n");
for (int i=0; i<dwReturnedBytes; i++)
{
wprintf(L"%02x ", sptsd.data[i]);
}
wprintf(L"\r\nEnd of returned data\r\n");
}
DEVICE_DESCRIPTOR dd;
b = DeviceIoControl(h, IOCTL_GET_DEVICE_DESCRIPTOR, &dd, sizeof(dd), &dd, sizeof(dd), &dwReturnedBytes, NULL);
if (b == 0)
{
LPTSTR errortext = ErrorMessage(GetLastError());
wprintf(L"DeviceIoControl(IOCTL_GET_DEVICE_DESCRIPTOR) failed with error %d : %s\r\n", GetLastError(), errortext);
LocalFree(errortext);
}
else
{
wprintf(L"DeviceIoControl(IOCTL_GET_DEVICE_DESCRIPTOR) succeeded\r\n");
wprintf(L"VendorId = %x, ProductId = %x, Version = %x\r\n", dd.usVendorId, dd.usProductId, dd.usBcdDevice);
wprintf(L"End of returned data\r\n");
}
CloseHandle(h);
}
return 0;
}
I tried both 32-bit and 64-bit versions of Windows 7 but the result is the same on both (error 50 : The request is not supported.). Interestingly, second DeviceIoControl call works and returns the VID/PID of the device, along with the firmware version.
Based on the error message, I would think this IOCTL is not supported. However, I looked into it and found out that this IOCTL code is mandatory for all devices, so there must be something I am doing wrong. How should this code be modified so that the INQUIRY command will succeed?
According to http://msdn.microsoft.com/en-us/library/ff548569%28v=vs.85%29.aspx, these IOCTL codes are recognized by the kernel-mode still image driver for USB buses.
IOCTL_CANCEL_IO
IOCTL_GET_CHANNEL_ALIGN_RQST
IOCTL_GET_DEVICE_DESCRIPTOR
IOCTL_GET_PIPE_CONFIGURATION
IOCTL_GET_USB_DESCRIPTOR
IOCTL_GET_VERSION
IOCTL_READ_REGISTERS
IOCTL_RESET_PIPE
IOCTL_SEND_USB_REQUEST
IOCTL_SET_TIMEOUT
IOCTL_WAIT_ON_DEVICE_EVENT IOCTL_WRITE_REGISTERS
My understanding is that any other IOCTL code should be sent via IOCTL_SEND_USB_REQUEST control code. This explains why trying to send a INQURY command using the above code does not work.
EDIT: It was simply a matter of using WriteFile to send the INQUIRY command and ReadFile to read the response. However, there seems an additional issue that I do not understand: The device wants an extra byte after the 6 bytes of the INQUIRY command to send the response. Otherwise, ReadFile will only return a single byte (0x3). I will update this reply again if I figure out what is happening here.

Sending http request repeatedly, more fast (async mode)

I need to send one request to server more quickly and repeatedly.
So I implemented code like this.
BOOL CTestDlg::OnInitDialog()
{
...
m_hInstance = InternetOpen(L"asynchttp", INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_ASYNC);
if(m_hInstance == NULL)
{
ErrorLog(L"InternetOpen Failed");
return TRUE;
}
if (InternetSetStatusCallback(m_hInstance,(INTERNET_STATUS_CALLBACK)&Callback) == INTERNET_INVALID_STATUS_CALLBACK)
{
ErrorLog(L"Set Callback Function Failed");
return TRUE;
}
m_hConnect = InternetConnect(m_hInstance, L"192.168.2.116", 8080,NULL,NULL,INTERNET_SERVICE_HTTP,INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_KEEP_CONNECTION,1);
if(m_hConnect == NULL)
{
if(DWORD dwError = GetLastError() != ERROR_IO_PENDING)
{
ErrorLog(L"Fail to Connect Server");
return TRUE;
}
WaitForSingleObject(hConnectedEvent, INFINITE);
}
CreateThread(0 , 0 , (LPTHREAD_START_ROUTINE)SendThread , 0 , 0 , 0);
return TRUE;
}
void __stdcall Callback(HINTERNET hInternet,DWORD dwContext,DWORD dwInternetStatus,LPVOID lpStatusInfo,DWORD dwStatusInfoLen)
{
switch(dwContext)
{
case 1:
{
SetEvent(hConnectedEvent);
}
break;
}
}
DWORD SendThread(LPVOID lpParam)
{
TCHAR *szAceptType[] = {_T("*/*") , NULL};
CString szContentType = _T("Content-Type: application/x-www-form-urlencoded\r\n");
char szPostData[MAX_PATH];
sprintf(szPostData , "num=1234&str=3240");
HINTERNET hRequest = HttpOpenRequest(m_hConnect, L"POST", L"/TestWeb/index.jsp", HTTP_VERSION , NULL , (LPCTSTR*)szAceptType , 0, 2);
while(1)
{
try
{
if (!HttpSendRequest(hRequest, szContentType, (DWORD)szContentType.GetLength(), szPostData,(DWORD)strlen(szPostData)))
{
if (DWORD dwError = GetLastError() != ERROR_IO_PENDING)
ErrorLog(L"SendRequest: Error = %d" , dwError);
}
}
catch (CException* e)
{
UNREFERENCED_PARAMETER(e);
}
Sleep(100);
}
return 0;
}
When execute or debug program, I saw this "SendRequest; Error = 1" log frequently.
And Server does not record anymore to database , after one or two request data recorded
It seems like HttpSendRequest API doesn't work correctly after error occured.
I aim to send one request to server more fast and more correctly, without loss.
Please teach me what is wrong problem.
Or if you got another best way, then please tell me.
Thanks.
Error code 1 is "Invalid Parameter".
You appear to be mixing ASCII (char and sprintf) and Unicode strings in your sample above. Have you tried with all Unicode strings (making szPostData a WCHAR array)? From MSDN: "There two versions of HttpSendRequest —HttpSendRequestA (used with ANSI builds) and HttpSendRequestW (used with Unicode builds)". It goes on to talk about when ERROR_INVALID_PARAMETER is returned. http://msdn.microsoft.com/en-us/library/windows/desktop/aa384247(v=vs.85).aspx
Also, I haven't used MFC in a long time, but I remember that you should call e->Delete() in your exception handler (unless you re-throw). The CException::Delete method will delete any thrown exception created on the heap (and do nothing otherwise).

FtpGetFile WinINEt never returns

I'm experiencing a curious problem (very strange, let me say hehe). During a FTP download of an EXE file (24 MB), if the connection is ever interrupted, it appears that the function FtpGetFile of the WinINEt library has a bug and it never returns. This causes that future file transfers fail (the connection is already opened).
Apparently, I found a workaround by increasing the timeout of the server transfers but I do not like it. I didn't found a similar problem by googling (maybe I introduced the wrong keywords).
I read some forums on the internet and it seems that everyone does not recommend using the FtpGetFile because it is buggy.
This appears in a network scenario that has a big lag (and not always) but in good conditions it disappears (downloads take place correctly and FtpGetFile returns always).
Here is how I use the function:
if( FtpGetFile(m_hFtpSession, strSourcePath.c_str(), strTargetPath.c_str(), 0, 0, FTP_TRANSFER_TYPE_BINARY, 0)==TRUE)
Can anyone confirm that? Should I refactor my code and look for an update?
Thank you
I found a way to download files without using FtpGetFile. I hope this code can help someone:
bool RetrieveFile(const string& strSource, const string& strTarget) {
/* The handle for the transfer */
HINTERNET hTransfer = NULL;
/*
* Set default error
*/
DWORD error = ERROR_SUCCESS;
if( !isConnected ) {
debug("%s(): ERROR not connected\n", __FUNCTION__);
return false;
}
/* Initiate access to a remote FTP connection */
hTransfer = FtpOpenFile(hFtpSession, strSource.c_str(), GENERIC_READ,
FTP_TRANSFER_TYPE_BINARY, 0);
if(hTransfer) {
std::ofstream myostream(strTarget.c_str(), std::ios::binary);
if ( myostream.is_open() ) {
static const DWORD SIZE = 1024;
BYTE data[SIZE];
DWORD size = 0;
do {
BOOL result = InternetReadFile(hTransfer, data, SIZE, &size);
if ( result == FALSE ) {
error = GetLastError();
Debug("InternetReadFile(): %lu\n", error);
}
myostream.write((const char*)data, size);
}
while ((error == ERROR_SUCCESS) && (size > 0));
// Close the stream
myostream.close();
}
else {
Debug("Could not open '%s'.\n", strTarget.c_str());
error = ERROR_FILE_NOT_FOUND; // Not necessarily not found, but it is to describe a file error which is different from ERROR_SUCCESS
}
// Close
const BOOL result = InternetCloseHandle(hTransfer);
if ( result == FALSE ) {
const DWORD error = GetLastError();
debug("InternetClose(): %lu\n", error);
}
/* Check error status of the process */
return (error == ERROR_SUCCESS);
}
DWORD dwInetError;
DWORD dwExtLength = 1000;
TCHAR *szExtErrMsg = NULL;
TCHAR errmsg[1000];
szExtErrMsg = errmsg;
int returned = InternetGetLastResponseInfo( &dwInetError, szExtErrMsg, &dwExtLength );
debug("dwInetError: %d Returned: %d\n", dwInetError, returned);
debug("Buffer: %s\n", szExtErrMsg);
debug("%s() : ERROR to get '%s' file (errorCode=%d)\n", __FUNCTION__, strSource.c_str(), GetLastError());
return false;
}