|
(I'm such a good boy)
it compiles ok when you fix the 2, 3 _very_ simple compilation errors (VC6 was a crappy compiler); and fix the unsafe functions (I did not fix them).
The project crashes because there are memory overruns (could be fixed by replacing unsafe functions with their safe variants.
Watched code never compiles.
|
|
|
|
|
|
Hi All,
I know there are a lot of people over here who have a diverse set of knowledge.
Why not we collaborate and start some C/C++ tools/application development that can benefit us and others also.
We can list out our skills, what tools are required and go about developing it and posting it out in CodeProject.
Please let me know your views on this.
~Thanks
Shakti
India, Bangalore
I am experienced in C/C++.
|
|
|
|
|
Shakti Misra wrote: Please let me know your views on this.
The question belongs here[^].
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Thanks. I have moved it there. I am not able to delete this post. So may be close it.
|
|
|
|
|
from msdn.microsoft.com - Enumerating Registry Subkeys:
http://msdn.microsoft.com/En-US/library/ms724256.aspx
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
void QueryKey(HKEY hKey)
{
TCHAR achKey[MAX_KEY_LENGTH]; DWORD cbName; TCHAR achClass[MAX_PATH] = TEXT(""); DWORD cchClassName = MAX_PATH; DWORD cSubKeys=0; DWORD cbMaxSubKey; DWORD cchMaxClass; DWORD cValues; DWORD cchMaxValue; DWORD cbMaxValueData; DWORD cbSecurityDescriptor; FILETIME ftLastWriteTime;
DWORD i, retCode;
TCHAR achValue[MAX_VALUE_NAME];
DWORD cchValue = MAX_VALUE_NAME;
retCode = RegQueryInfoKey(
hKey, achClass, &cchClassName, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, &cValues, &cchMaxValue, &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime);
if (cSubKeys)
{
printf( "\nNumber of subkeys: %d\n", cSubKeys);
for (i=0; i<cSubKeys; i++)
{
cbName = MAX_KEY_LENGTH;
retCode = RegEnumKeyEx(hKey, i,
achKey,
&cbName,
NULL,
NULL,
NULL,
&ftLastWriteTime);
if (retCode == ERROR_SUCCESS)
{
_tprintf(TEXT("(%d) %s\n"), i+1, achKey);
}
}
}
if (cValues)
{
printf( "\nNumber of values: %d\n", cValues);
for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++)
{
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
retCode = RegEnumValue(hKey, i,
achValue,
&cchValue,
NULL,
NULL,
NULL,
NULL);
if (retCode == ERROR_SUCCESS )
{
_tprintf(TEXT("(%d) %s\n"), i+1, achValue);
}
}
}
}
void __cdecl _tmain(void)
{
HKEY hTestKey;
if( RegOpenKeyEx( HKEY_CURRENT_USER,
TEXT("SOFTWARE\\Microsoft"),
0,
KEY_READ,
&hTestKey) == ERROR_SUCCESS
)
{
QueryKey(hTestKey);
}
RegCloseKey(hTestKey);
}
how can i modify that code at:
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
retCode = RegEnumValue(hKey, i,
achValue,
&cchValue,
NULL,
NULL,
NULL,
NULL);
if (retCode == ERROR_SUCCESS )
{
_tprintf(TEXT("(%d) %s\n"), i+1, achValue);
}
to output to the console all the values that RegEnumValue function can return, function at msdn: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724865%28v=vs.85%29.aspx i want to output these vars too:
__out LPTSTR lpValueName,
__inout LPDWORD lpcchValueName,
__out_opt LPDWORD lpType,
__out_opt LPBYTE lpData,
__inout_opt LPDWORD lpcbData
i have tried different things but everytime i change any of NULL var from that function:
retCode = RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL, NULL, NULL);
i even don´t get achValue
thanks a lot
PD using windows 7 64 bits visual studio 2010 ultimate
|
|
|
|
|
You need to initialize your parameters as described in the documentation[^], so that the API knows how long your buffers are and what values you want returned. Using NULL as the input parameter tells the API to ignore that part of the request.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
You could do it like this:
int datatype;
unsigned char *value;
int sizeofvalue;
if(RegEnumValue(hKey,i,achValue,&cchValue,0,&datatype,value,&sizeofvalue) == ERROR_SUCCESS){
switch(datatype){
case REG_DWORD:
printf("%d",*((int*)value));
break;
case REG_NONE:
printf(...);
break;
case REG_EXPAND_SZ:
printf(...);
break;
case REG_SZ:
printf(...);
break;
case REG_MULTI_SZ:
printf(...);
break;
default:
printf(...);
break;
}
}
Where datatype will identify the type of information, achValue the name of the value, value the actual value and sizeofvalue the size of the value.
I added an example printf for REG_DWORD.
modified 13-Sep-18 21:01pm.
|
|
|
|
|
As mentioned in my response, this still will not get the values since the variables datatype , value and sizeofvalue need to be initialised before each call to RegEnumValue() .
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
I am interested in using my static lib to create a dll (implicitly linking). which means I need to (in vs2008) create a dll project that should generate the following:
1. header file (which have exported function declarations. These are simple wrappers to actual functions in the static lib and are using __declspec(dllexport) which are in the dll centric .cpp file)
2. import lib which will be made as a result of creating the dll
3. the actual dll which is created.
Now this is what I have:
I have made a test program that will utilize the above dll(including the import lib/header files) to test it. in this I have included all the three items. now the exe compiles/links without issue. however in the main.cpp when i call the exported functions they seem to see the exported dlls...but can't seem to execute the static library functions which they wrap.
i have tested the static lib against the exe and it works fine.
but when i put the dll in between the wrappers just dont seem to run the static library functions... i am at a loss.
there are no compile/link errors. no warnings. i am just thinking hhow do i find out if the static lib is properly being used by the dll? i have no way of knowing that i guess in vs2008. any help would be most apprecaited
|
|
|
|
|
Android Lava wrote: when i call the exported functions they seem to see the exported dlls...but can't seem to execute the static library functions which they wrap.
I'm not sure I understand what you mean here. Are you saying that the functions inside the DLL are supposed to call functions inside the static library? If that is the case then the static library needs to be linked in to your DLL when it is built.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
How do you know it's not calling the functions? Is the output wrong? Are you using breakpoints in the static library and seeing that you are not getting there?
If I get what you are doing, you should have TWO copies of the static library functions in your final memory image, one copy accessed by the main code and linked in when the main.exe is built and one copy inside the DLL itself that was linked in when the DLL file was created.
So, you say "can't seem to execute the static library functions". How have you determined that?
|
|
|
|
|
I don't understand the question. At a minimus perhaps it has two parts.
Part 1: If you want to write code to create a dll (not use an existing one) then you need to deal with doing just that. HOW the dll is used after that is irrelevant to this part of the code. And if I was doing it I would create source code and then plan on providing a compiler/linker which I would then call from the code so that those created the dll.
Part 2: There is code X that uses a dll Y. If Y does not exist when X is created then X must call the dll dynamically. Y of course must be a dll (or another type of binary that can be dynamically loaded.) X cannot randomly use any Y. X must know/assume some behavior of Y. So X loads Y, then looks for exactly the functionality that it demands. Then it calls that.
The two parts have nothing to do with each other. Implement them and test them independently from each other.
|
|
|
|
|
straight win32 app
I used the URLDownloadToFile to download a program file, probably a mistake, but a start at least. I wrote my IBindStatusCallback, and attached it to the URL program.
So I have a Window, not a dialog box, probably another mistake, I call the function in my window, and the function runs, but the wndproc in the window stops running, so my cancel button won't fire.
I tried to think of a way, that allows the OnProcess loop to give control back to the window, so I can capture the cancel button, but no luck.
Any points in the right direction would be helpful. I did see the data exchange thing, but thought it was for dialog boxes. This is my first experience in this.
|
|
|
|
|
Well, you could start a separate thread to do the URLDownloadToFile call and let the OnProcess (which I assume is your button) to return processing windows messages.
You would have to implement a "completion" message back from the thread to the main window to tell it when the download was complete and return the status of the download (success, fail, cancelled).
You cancel button should then work but, of course, you now need to tell the thread that the cancel button was hit or test a "cancelled" flag in the callback.
|
|
|
|
|
I was just reading up on creating threads.
So I guess I would create a thread in the window code, and run the class code in the thread.
Creating a thread looks like it takes alot of code.
Maybe the cancel button is not worth it.
|
|
|
|
|
Nah, creating thread is pretty straightforward, there are lots of examples here on code project. A quick search should find several like this CThread - a Worker Thread wrapper class[^]
Or you can use CWinThread (if you're derived from CWinApp). Or use _beginthreadex()[^] native Windows API.
Threads is a good thing to learn early. In this case, you can create the simplest of thread routines and not worry about complicated events and synchronization later. Just get it to do your download and send a completion message to your main windows process.
|
|
|
|
|
Well since I used the simplest way to download, the simplest thread sounds like a good idea. I'll start that tomorrow.
Right now I'm experimenting with creating a cancel button in the download class, and seeing if I can capture the message when the button is clicked. I got the button to appear and position itself with the right font in the Callback under BINDSTATUS_CONNECTING
I wrapped the original call to the class in a do loop, to keep it from progressing. Got the idea from the socket code I wrote.
I'm just messing around right now, experimenting till morning.
do {
bResult = caDownload._download_SQLServerExpress_GUI(cWnd, pb_SQL_Server_Download_Status, lbl_SQL_Server_Download_Status, bAreWeX64 );
} while (bResult == FALSE);
|
|
|
|
|
Which one was the easy one?, they both look intimidating.
|
|
|
|
|
They're both a lot easier having done them than before. I had no idea about threads or sockets 2 1/2 weeks ago, but have now learnt enough to get by and have cobbled together a rss reader - one which can pre-load all subscribed feeds in parallel, each in it's own thread.
Notifying the main window of a thread's completion is the easier of the two. Without MFC, it's as (1) defining a user message, and deciding on the format (if any) of the passed information (2) sending that message to the main window upon completion (3) handling that message in the main window.
E.g
Part 1 - Main window completion notification mechanism
#define WM_GALLERY_HTML_AVAILABLE WM_USER+1
#define WM_FILE_DOWNLOAD_COMPLETE WM_USER+2
...
...
...
__stdcall void galleryHtmlDownloadedCallbackFunc(PVOID data)
{
downloadHeader_t *hdr;
hdr = (downloadHeader_t*)data;
galHtmlStr = hdr->result;
galUrlStr = hdr->szUrl;
free(hdr->result);
hdr->result = NULL;
hdr->contentLen = 0;
PostMessage(mainDlgWnd, WM_GALLERY_HTML_AVAILABLE, 0, 0);
}
...
...
...
...
case WM_INITDIALOG:
mainDlgWnd = hwndDlg;
editWnd = GetDlgItem(hwndDlg, IDC_RICHEDIT1);
SetFocus(GetDlgItem(hwndDlg, IDC_RICHEDIT1));
return FALSE;
case WM_FILE_DOWNLOAD_COMPLETE:
return true;
case WM_GALLERY_HTML_AVAILABLE:
findLinks((char*)galHtmlStr.c_str(), links, validExts);
strLinks.clear();
printf("Number of links: %d\n", links.size());
for (i=0; i<links.size(); i++)
strLinks += links[i] + "\n";
SetDlgItemText(mainDlgWnd, IDC_RICHEDIT1, strLinks.c_str());
return true;
case WM_CLOSE:
EndDialog(hwndDlg, 0);
return TRUE;
Part 2 - Threading mechanism
static downloadHeader_t curDownload;
GetWindowText(urlHwnd, szUrl, urlLen+1);
savePath = getFolderName(mainDlgWnd, "C:\\001");
if (strlen(szUrl) && strlen(savePath))
{
curDownload.szUrl = szUrl;
curDownload.callback = (voidFuncPtr)galleryHtmlDownloadedCallbackFunc;
curDownload.saveFilePath = savePath;
_beginthread(DownloadThread, NULL, (void*)&(curDownload));
}
delete savePath;
delete szUrl;
typedef void (*voidFuncPtr)(void*);
struct downloadHeader_t
{
string szUrl; voidFuncPtr callback; string saveFilePath; PVOID lParam;
SOCKET conn;
char *readBuffer, *sendBuffer, *tmpBuffer, *result;
string server, filepath, filename;
long thisReadSize, headerLen, contentLen;
};
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename)
{
string::size_type n;
string url = mUrl;
if (url.substr(0,7) == "http://")
url.erase(0,7);
n = url.find('/');
if (n != string::npos)
{
serverName = url.substr(0,n);
filepath = url.substr(n);
n = filepath.rfind('/');
filename = filepath.substr(n+1);
}
else
{
serverName = url;
filepath = "/";
filename = "";
}
}
SOCKET connectToServer(char *szServerName, WORD portNum)
{
struct hostent *hp;
unsigned int addr;
struct sockaddr_in server;
SOCKET conn;
conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (conn == INVALID_SOCKET)
return NULL;
if(inet_addr(szServerName)==INADDR_NONE)
{
hp=gethostbyname(szServerName);
}
else
{
addr=inet_addr(szServerName);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
return NULL;
}
server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
server.sin_family=AF_INET;
server.sin_port=htons(portNum);
if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
{
closesocket(conn);
return NULL;
}
return conn;
}
int getHeaderLength(char *content)
{
const char *srchStr1 = "\r\n\r\n", *srchStr2 = "\n\r\n\r";
char *findPos;
int ofset = -1;
findPos = strstr(content, srchStr1);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr1);
}
else
{
findPos = strstr(content, srchStr2);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr2);
}
}
return ofset;
}
void __stdcall DownloadThread(void *dat)
{
downloadHeader_t *hdr;
hdr = (downloadHeader_t *)dat;
const int bufSize = 512;
printf("download thread - \n");
hdr->result = NULL;
hdr->readBuffer = (char*)malloc(bufSize);
hdr->sendBuffer = (char*)malloc(bufSize);
hdr->tmpBuffer = (char*)malloc(bufSize);
printf("download thread - \n");
mParseUrl((char*)hdr->szUrl.c_str(), hdr->server, hdr->filepath, hdr->filename);
printf("download thread - \n");
hdr->conn = connectToServer((char*)hdr->server.c_str(), 80);
if (hdr->conn)
printf("download thread - connected?\n");
sprintf(hdr->tmpBuffer, "GET %s HTTP/1.0", hdr->filepath.c_str());
strcpy(hdr->sendBuffer, hdr->tmpBuffer);
strcat(hdr->sendBuffer, "\r\n");
sprintf(hdr->tmpBuffer, "Host: %s", hdr->server.c_str());
strcat(hdr->sendBuffer, hdr->tmpBuffer);
strcat(hdr->sendBuffer, "\r\n");
strcat(hdr->sendBuffer, "\r\n");
send(hdr->conn, hdr->sendBuffer, strlen(hdr->sendBuffer), 0);
hdr->contentLen = 0;
while(1)
{
memset(hdr->readBuffer, 0, bufSize);
hdr->thisReadSize = recv (hdr->conn, hdr->readBuffer, bufSize, 0);
if ( hdr->thisReadSize <= 0 )
break;
hdr->result = (char*)realloc(hdr->result, hdr->thisReadSize+hdr->contentLen);
memcpy(hdr->result+hdr->contentLen, hdr->readBuffer, hdr->thisReadSize);
hdr->contentLen += hdr->thisReadSize;
}
hdr->headerLen = getHeaderLength(hdr->result);
hdr->contentLen -= hdr->headerLen;
memmove(hdr->result, hdr->result+hdr->headerLen, hdr->contentLen);
realloc(hdr->result, hdr->contentLen+1);
hdr->result[hdr->contentLen] = 0x0;
closesocket(hdr->conn);
free(hdr->readBuffer);
free(hdr->sendBuffer);
free(hdr->tmpBuffer);
if (hdr->callback)
hdr->callback(hdr);
}
|
|
|
|
|
Nice job on the code modules. I can see that creating a thread to run the program in is not that difficult. I have an idea of the components needed now after examining your sample.
Let's see what I can some up with today. I'll be back.
|
|
|
|
|
Not a problem.
I just noticed that I declared the DownloadThread function as being __stdcall. It's a mistake, and should read __cdecl. Errors with calling conventions are, I suspect, begin the majority of my program crashes.
FWIW, it's _beginthreadex that wants a thread function called using __stdcall.
|
|
|
|
|
I didn't run your sample. I just examined it for reverse engineering to suit my needs.
I spend half a day yesterday cleaning up my code, but was not able to successfully test my thread. I got confused with how the process worked. In other words, I show the cancel button, then I run a function, and the cancel button won't send a message back to wndproc until it completes. So I messsed around with the way I made the original class, and fixed my mistakes.
Today I will try to get my thread working.
|
|
|
|
|
He, he. I'm familiar with that feeling. It took me quite a while to wrap my head around when and where was the appropriate place to do things. I've since re-done the function such that it can send progress callbacks too.
Haven't bothered with a cancel functionality yet - though I'd imagine it to be a simple matter of setting a flag from the main program thread, checking this flag each time through the receive loop in the download thread. (may have to use a mutex to access the flag in a safe manner)
|
|
|
|
|
I have the create thread working now. just went simple on it.
I already had the progress bar and status text working, now the new thread launches the download, and the cancel button responds to my click. I know how to stop the Download Callback with E_ABORT, I just need to figure out how to send that message to the progress loop.
After that, I need to figure out how to destroy the thread on cancel, or when the download is complete, _endthread,
but I'm not sure if I need to close the handle, and the WaitForObject.
Getting there. Still experimenting with it, so it's not finalized.
hThread = (HANDLE)_beginthreadex(NULL, 0, SQL_SoftwareDownload, NULL, 0, (unsigned *)&thread_id);
return resultCode;
}
unsigned int __stdcall SQL_SoftwareDownload(void *) {
int iReturn = 0;
HRESULT hr = E_FAIL;
callback = new SQL_Servers_BindCallback;
callback->m_MDIChild = hSQL_Servers_Download;
callback->m_Progress_Text = lbl_SQL_Server_Download_Status;
callback->m_Progress_Bar = pb_SQL_Server_Download_Status;
callback->b_Downloading = TRUE;
hr = URLDownloadToFile(NULL, szUrl, szFileName, 0, callback);
if (hr == S_OK)
iReturn = 1;
return iReturn;
}
|
|
|
|
|