|
Hi All,
In an effort to keep my mind active, I've decided to attempt to learn Unmanaged C/C++ - ideally C first and ++ later - however given the range of books and tools available, I wondered if anyone had any recommendations they could share?
In terms of tools, I have VS2005 Pro but every time I fire it up and open a MFC project i quickly get lost (and I think I'm right in thinking that a lot of what you can do in VS2005 is tied to MS platforms?), so if anyone can recommend a equally good (but hopefully more streamlined!) IDE for C, I'd be glad to hear it!
TVM,
Martin.
|
|
|
|
|
There is a free IDE called 'Dev C++' (Google for it's URL). You can do both C and C++. For a free IDE, it's pretty good. If you want to use VC++ as your IDE, try creating your applications as: Win32 Console Application or Win32 Application.
Learn C first before jumping stright into C++. Read about object-oriented programming before tackling C++, and learn about 'event-driven' programming before you step into using MFC. One book that I used when learning MFC (and I'm by no means an expert) was 'MFC Programming' by Ivor Horton. Hopefully, there is an updated version which covers the latest MFC IDEs.
Good luck, and don't get frustrated. It will take you probably 6 months after starting to use C++ before you feel comfortable with it.
John P.
|
|
|
|
|
jparken wrote: Learn C first before jumping stright into C++.
My advice would be the opposite.
Steve
|
|
|
|
|
Stephen Hewitt wrote: My advice would be the opposite.
So is this how you would say it in an opposite way?...
Learn C++ first before jumping straight into C. Read about C++ before tackling object-oriented programming, and learn about MFC before you step into using 'event-driven' programming . One book that I would never recommend when learning MFC (and I'm an expert) is 'MFC Programming' by Ivor Horton. Hopefully, there is not an updated version which covers the latest MFC IDEs.
|
|
|
|
|
Once you know C++, learning C is simply a matter of learning what's missing (for the most part). Learning C++ teaches you better coding habits however. That's how I was taught it at uni. The lecturers tried it both ways and found this way the best (or so I was told).
Steve
|
|
|
|
|
Structured programming is much easier for a first semester in programming.
We actually started with Pascal in High school and college and C was offered next in the progression with Pascal as a prerequisite.
|
|
|
|
|
I disagree. Object oriented programming is very intuitive because it lines up with the way people naturally think. That's why it was invented: to help manage the ever increasing complexity of software development by making it easier to understand. I don’t think of a door as a set of states and disconnected functions for manipulating and interrogating the state but rather as a single object. It’s often harder for people who have learnt structured programming first because they have to change their mind set, but that’s not the point under discussion.
Steve
|
|
|
|
|
bob16972 wrote: Learn C++ first before jumping straight into C.
Yep.
Learn proper object-oriented design and architecture, before stepping into the world of wonders of C.
Too many people try to write C++ as if it were a C with classes.
C is a sophisticated macro-assembler. C++ is an object-oriented language with the possibility to fall back to C.
Failure is not an option - it's built right in.
|
|
|
|
|
jhwurmbach wrote: C is a sophisticated macro-assembler.
I think this is the bit I'm most interested in... not least, because I don't even know what that means!
|
|
|
|
|
20 years or so ago, I made the change from Pascal / Basic / whatever was handy to C.
I learnt C programming, and have never made the step to C++ - it just didn't seem to have any real benefits. And yes, I have heard about code reusability, encapsulation, and all those supposed benefits of Object-Oriented Programming. They just don't seem to be enough of an advantage that it's worth changing my way of doing things.
I even bought some books - the first 20 pages of each are well-thumbed, but then the concepts (sorry, "paradigms") became so ridiculous and contrived, I gave up each time.
Unfortunately, the world has moved on. Everyone except me has moved from C to C++ to C#. Sob.
So to avoid my experience, I would advise skipping the ANSI C stage, and moving straight to C++ or C#. But since I have not done this, I can't recommend any books.
|
|
|
|
|
Hello everybody
I am trying to make a proxy(/wrapper) dll for wsock32.dll.
Therefore i used the script found here: "http://www.codeproject.com/dll/CreateYourProxyDLLs.asp"
The "default" result of this script (with the asm jmp functions) works perfectly, but when i try to manipulate
the parameters passed to my proxy functio. i get an access violation error.
i am trying to "proxify" the send function
according to MSDN ( http://msdn2.microsoft.com/en-us/library/ms740149.aspx) :
int send(
SOCKET s,
const char* buf,
int len,
int flags
);
Therefore i replaced script generated functions:
-------------Code--------------
// send
extern "C" __declspec(naked) void __stdcall __E__69__()
{
__asm
{
jmp p[69*4];
}
}
-------------Code--------------
With my own ( for handeling the parameters )
-------------Code--------------
// customizable send
extern "C" int __stdcall __E__69__( SOCKET s, const char* buf, int len, int flags )
{
//we must type cast the "remote" function
typedef int (*__stdcall ps)( SOCKET, const char* , int , int);
ps PX;
PX = (ps)p[69*4];
//Returning response from real dll
return (*PX)( s, buf, len, flags );
}
-------------Code--------------
and compile the above.
Compiling goes without warning or erors.
If i then place the proxy dll along side the original dll (properly named)
and lauch the application (which uses my proxy dll ) i get an acces violation like the following:
------------------------Error-----------------------------------
This application has encountered a critical error:
Error #132 (0x85100084) Fatal Exception
Exception: 0xC0000005 (ACCESS_VIOLATION) at 001B:00000000
The instruction at "0x00000000 referenced memory at "0x00000000".
The memory could not be "read"
Press OK to terminate the application
------------------------Error-------------------------------------
With the following stack trace:
------------------------Stack Trace-----------------------------------
10001A3B WSOCK32.dll __E__69__+27 (0x00002454,0x0012FDF7,0x00000001,0x00000000) (wsock32.cpp,756)
00603AAD WoW.exe <unknown symbol="">+0 (0x00000000,0x00000000,0x00000000,0x00000000)
------------------------Stack Trace-----------------------------------
I would be very gratefull if someone could help me solve this problem.
Thanks in advance
|
|
|
|
|
Cloather2 wrote: 10001A3B WSOCK32.dll __E__69__+27 (0x00002454,0x0012FDF7,0x00000001,0x00000000) (wsock32.cpp,756)
00603AAD WoW.exe +0 (0x00000000,0x00000000,0x00000000,0x00000000)
If that WoW.exe is World Of Warcraft, and you are trying to crack the C/S protocol or create some kind of cheating (aiming/environmental) proxy, you are far out of your league if you are getting problems like this...!
Peace!
-=- James Please rate this message - let me know if I helped or not!<HR> If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|
|
Ye i get it, ill go somewhere else
-- modified at 2:24 Friday 11th May, 2007
Solved it myself by:
putting following type def at top of file:
------------Code-------------------
typedef void (CALLBACK *PTTOSEND)(SOCKET, const char*, int, int);
Instead of the default array var to hold the func pointer i created my own var like this:
------------Code-------------------
ptToSend = (PTTOSEND) GetProcAddress(hL,"send"); //type cast
The function call then looks like this
------------Code-------------------
// customizable send
extern "C" void __stdcall __E__69__( SOCKET s, const char* buf, int len, int flags )
{
//Returning response from real dll
return (*ptToSend)( s, buf, len, flags );
}
|
|
|
|
|
Good luck with that...!
Peace!
-=- James Please rate this message - let me know if I helped or not!<HR> If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|
|
I use a third part COM API lib. I need to pass an array of double to a method which accept VARIANT*, Is there any simple way to cast from double* to VARIANT*, I don't want to create a VARIANT array and copy each double value into.
|
|
|
|
|
The VARIANT can hold a SAFEARRAY , which you would have to populate with the set of double s.
There is no other COM-correct way to do what you are trying to do without changing the interface (i.e. breaking the contract).
Peace!
-=- James Please rate this message - let me know if I helped or not!<HR> If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|
|
There is no other way at all, if you don't have the COM component source code (of course without hacking...).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
|
|
|
|
|
Hi folks,
I am new to the forum and a beginner in c++ programming.
I have finished writing an application in c++ and I would now like to protect it so that only people who know the unlocking code can have access to it.
I was thinking of doing so by creating a key in the registry directory containing a random sequence of numbers and then have the program read it, perform some mathematical ops, and request the user the relative unlocking numbers for the program to run.
The idea seems simple. The only problem is that I have no clue whatsoever on how to write and read a registry key!!
I would be very grateful for any help. I am stuck!
Thank you.
|
|
|
|
|
Lookup the implementation of the CRegKey class in your SDK for a good starting point, as well as the MSDN documentation for Registry-related functions like RegCreateKeyEx(...) .
Peace!
-=- James Please rate this message - let me know if I helped or not!<HR> If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|
|
Dear James,
Thanks for the help.
I've looked up the RegCreateKeyEx function on MSDN, as you have suggested. I have tried to copy the code present in the second coloured box at (http://msdn2.microsoft.com/en-us/library/aa363634.aspx) into my c++ code, but I am sure I am either missing something crucial or inserting it in the wrong location, since it is returning a thousand errors when I try to compile it!
Not sure what I am doing wrong. Consider that I am a real beginner. My code is all written in c++ using VS2005 and Win32 application.
My code looks like that:
<code>#include "stdafx.h"
#include <ctime>
#include <math.h>
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
#include <iomanip>
using std::setprecision;
int _tmain(int argc, _TCHAR* argv[])
{
// my code
return 0;
}</code>
Thank you!
J_E_D_I
|
|
|
|
|
One problem you might be having is that you are not linking with the correct libraries to support the new functions you have added.
The RegCreateKeyEx() function requires that your program be linked with Advapi32.lib. Have you added this library to you project's linker input settings?
You would add the name "Advapi32.lib" to where it says "Additional Dependencies" in the Project Settings dialog box.
--------------------------------
"All that is necessary for the forces of evil to win in the world is for enough good men to do nothing" -- Edmund Burke
|
|
|
|
|
Many thanks for the advice.
I have added the Advapi32.lib to the Additional Dependencies and tried to compile it (code below) but it results in many errors.
I would be very grateful for any advice.
#include "stdafx.h"
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
#include <iomanip>
using std::setprecision;
int _tmain(int argc, _TCHAR* argv[])
{
CString default_server;
CString default_root_dir;
CStringArray servers;
CStringArray rootdirs;
default_server = "";
default_root_dir = "";
servers.RemoveAll();
rootdirs.RemoveAll();
/* Read FTP server name and root directories from registry. GetRegistryList reads all the key values and fill in
the CString array */
HKEY hKey = GetRegistryKey( "Server" );
GetRegistryList( hKey, default_server, servers);
/* Now read it from array and add to a combo box */
for(int i=0; i<servers.getsize(); i++="" )
{
cstring="" str="servers[i].Left(" servers[i].find("#")="" );
combo-="">AddString( str );
}
Now, here is how to add one registry entry to the registry.
AddRegValue("Server", m_szftpServerName , m_szWebRootDir );
Now, here is how to delete a key and its corresponding value from the registry:
AddRegValue("Server", m_szftpServerName , m_szWebRootDir );
/* ************************************************************
Registry functions STARTS
************************************************************/
HKEY GetRegistryKey( CString str )
{
HKEY hViewerKey = NULL;
HKEY hSoftDirKey = NULL;
HKEY hCompanyKey = NULL;
HKEY hCompanyDirKey = NULL;
CString m_pszRegistryKey = "MIS Inc.";
CString m_pszProfileName;
m_pszProfileName = "Settings";
CString section = str;
//read from the registry...for default viewer
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSoftware, 0, KEY_WRITE|KEY_READ, &hSoftDirKey)
== ERROR_SUCCESS)
{
DWORD dw;
if (RegCreateKeyEx(hSoftDirKey, (LPCTSTR)m_pszRegistryKey, 0, REG_NONE, REG_OPTION_NON_VOLATILE,
KEY_WRITE|KEY_READ, NULL, &hCompanyKey, &dw) == ERROR_SUCCESS)
{
if(RegCreateKeyEx(hCompanyKey, (LPCTSTR)m_pszProfileName, 0, REG_NONE, REG_OPTION_NON_VOLATILE,
KEY_WRITE|KEY_READ, NULL, &hCompanyDirKey, &dw) == ERROR_SUCCESS)
{
RegCreateKeyEx(hCompanyDirKey, (LPCTSTR)section, 0, REG_NONE, REG_OPTION_NON_VOLATILE,
KEY_WRITE|KEY_READ, NULL, &hViewerKey, &dw);
}
}
}
if (hCompanyKey != NULL)
RegCloseKey(hCompanyKey);
if (hSoftDirKey != NULL)
RegCloseKey(hSoftDirKey);
if (hCompanyDirKey != NULL)
RegCloseKey(hCompanyDirKey);
return hViewerKey;
}
BOOL GetRegistryList(HKEY hKey, CString &strValue, CStringArray &keyValue)
{
// HKEY hKey = GetConversionKey( "Data" );
DWORD dwType, dwCount;
long index = 0;
LONG lResult = 0;
CHAR ValueName[max_value];
DWORD dwcValueName = max_value;
CString data;
ValueName[0] = '\0';
dwCount = max_value;
lResult = RegEnumValue(hKey,index,ValueName,//regenumvalue return the key value names.
&dwcValueName, NULL, &dwType, NULL, &dwCount);
while(lResult != ERROR_NO_MORE_ITEMS)
{
RegQueryValueEx(hKey, ValueName, NULL, &dwType, (LPBYTE)data.GetBuffer(dwCount/sizeof(TCHAR)),
&dwCount);
data.ReleaseBuffer();
CString str = (CString)ValueName;
if(!(str.IsEmpty())) //neglecting the default value.
{
str = (CString)ValueName + "#" + data;
//concatenating the key value and its data
//separating with #
keyValue.Add((LPCTSTR)str);
}
++index;
dwcValueName = max_value;
lResult = RegEnumValue(hKey,index,ValueName, &dwcValueName,NULL,&dwType,NULL, &dwCount);
}
//this call is for default viewer.
lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, NULL, &dwCount);
if (lResult == ERROR_SUCCESS)
{
ASSERT(dwType == REG_SZ);
lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)strValue.GetBuffer(dwCount/sizeof(TCHAR)),
&dwCount);
strValue.ReleaseBuffer();
}
RegCloseKey(hKey);
if (lResult == ERROR_SUCCESS)
{
ASSERT(dwType == REG_SZ);
return TRUE;
}
return FALSE;
}
BOOL GetLeftRegistryList(HKEY hKey, CString &strValue, CStringArray &keyValue)
{
// HKEY hKey = GetConversionKey( "Data" );
DWORD dwType, dwCount;
long index = 0;
LONG lResult = 0;
CHAR ValueName[max_value];
DWORD dwcValueName = max_value;
CString data;
ValueName[0] = '\0';
dwCount = max_value;
lResult = RegEnumValue(hKey,index,ValueName,//regenumvalue return the key value names.
&dwcValueName, NULL, &dwType, NULL, &dwCount);
while(lResult != ERROR_NO_MORE_ITEMS)
{
RegQueryValueEx(hKey, ValueName, NULL, &dwType, (LPBYTE)data.GetBuffer(dwCount/sizeof(TCHAR)),
&dwCount);
data.ReleaseBuffer();
CString str = (CString)ValueName;
if(!(str.IsEmpty())) //neglecting the default value.
{
str = (CString)ValueName;
//concatenating the key value and its data
//separating with #
keyValue.Add((LPCTSTR)str);
}
++index;
dwcValueName = max_value;
lResult = RegEnumValue(hKey,index,ValueName, &dwcValueName, NULL, &dwType, NULL, &dwCount);
}
//this call is for default viewer.
lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, NULL, &dwCount);
if (lResult == ERROR_SUCCESS)
{
ASSERT(dwType == REG_SZ);
lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)strValue.GetBuffer(dwCount/sizeof(TCHAR)),
&dwCount);
strValue.ReleaseBuffer();
}
RegCloseKey(hKey);
if (lResult == ERROR_SUCCESS)
{
ASSERT(dwType == REG_SZ);
return TRUE;
}
return FALSE;
}
BOOL AddRegValue(const CString& key, const CString& value, const CString& data)
{
HKEY hKey = GetRegistryKey(key);
LPCTSTR lpszEntry = value;
LPCTSTR lpszValue = data;
if (hKey == NULL)
return FALSE;
LONG lResult = RegSetValueEx(hKey, lpszEntry, NULL, REG_SZ, (LPBYTE)lpszValue, (lstrlen(lpszValue)+1)*sizeof
TCHAR));
RegCloseKey(hKey);
//adding in the registry so that number of extensions can be retrieved
//for which the viewers are added.
SetKruseExtension(value, data);
if(lResult == ERROR_SUCCESS)
return TRUE;
else
return FALSE;
}
BOOL DeleteRegValue(const CString& key, const CString& value, const CString& data)
{
HKEY hKey = GetRegistryKey(key);
LPCTSTR lpszEntry = value;
LPCTSTR lpszValue = data;
if (hKey == NULL)
return FALSE;
LONG lResult = RegSetValueEx(hKey, lpszEntry, NULL, REG_SZ, (LPBYTE)lpszValue, (lstrlen(lpszValue)+1)*sizeof
TCHAR));
RegCloseKey(hKey);
//adding in the registry so that number of extensions can be retrieved
//for which the viewers are added.
SetKruseExtension(value , data);
if(lResult == ERROR_SUCCESS)
return TRUE;
else
return FALSE;
}
/* ************************************************************
Registry functions ENDS
************************************************************/
return 0;
}
|
|
|
|
|
try using CRegKey!
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|
I have a table filled in from reading a text file and I load that into a multi column CListCtrl, which is fine, I can also append to columns in there.
Is there an easy way to delete a specific column on a specific row?
What I'm doing right now:
a dialog button "Clear Entry" calls GetSelectionMark() on the table, and uses that to set the columns to "" in a rather heavy handed way
LVITEM lvi;
CString item = "";
lvi.mask = LVIF_IMAGE | LVIF_TEXT;
lvi.iItem = sel;
lvi.iSubItem = 3;
lvi.pszText = (LPTSTR)(LPCTSTR)(item);
m_Table.SetItem(&lvi);
lvi.iSubItem = 5;
lvi.pszText = (LPTSTR)(LPCTSTR)(item);
m_Table.SetItem(&lvi);
this seems to work fine, though there are issues
1) if the table hasnt been clicked there is no selection mark.
2) you can only click on the 1st column in a particular row - this is fine, but if I then click "Clear Entry" button, it works OK but the blue highlight disappears like that row is no longer selected but if I add data there and click "Clear Entry" it seems to remember what was last selected and deletes those items - a bit messy
I see DeleteAllItems and DeleteColumn, but how can I delete just one item on one particular row in an elegant way?
tia
L
|
|
|
|
|
ldsdbomber wrote: 1) if the table hasnt been clicked there is no selection mark.
So just disable the "clear" button until a selection is made.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|