|
Project -> Properties -> Configuration Properties -> C/C++ -> Code Generation -> Runtime Library .
Set this to /MT and /MTd for Release mode and Debug mode respectively.
|
|
|
|
|
It is already set , if I installed vcredist_x86.exe then exe run , if uninstall then exe do not run .
i am using Use Standard Windows Libraries in release mode
Trioum
|
|
|
|
|
Besides the setting for the C RTL (/MT etc...) you also need to check the Configuration Properties -> General for the "Use of MFC" and "Use of ATL". Both of those have a selection for "in a static library". The default to "use standard windows libraries" which means "shared DLL".
I use VS2008 but I think they are in the same place in VS2005
|
|
|
|
|
You don't HAVE to install visual studio, there's probably some dependencies that you need to distribute along with your application so that it'll be complete. Use a tool like Dependency Walker[^] to figure out what libraries you may be missing. You can then either include those libraries in your distribution OR build them into your executable statically (depending on what libraries you may be missing).
|
|
|
|
|
I copied some sample code from msdn to create a socket, and modified it for testing. I want to broadcast a udp dgram, but I cant figure out what to send. I'm using ethereal to examine what SQL Management sends, and I'm trying to copy the behavior. So it looks like my first send is accurate, but I'm not sending the correct data out for a response back from sqlbrowser. I'm convinced if I send the right stuff, I will get my responses back from all the SQL servers. If i'm in the wrong forum sorry, didn't really know where to post it.
I tried 0x02 in the send buffer.
iResult = getaddrinfo(
"255.255.255.255",
"ms-sql-m",
&hints,
&result
);
I think this is what SQL Management sent
0000 ff ff ff ff ff ff 00 13 72 36 67 30 08 00 45 00 ........ r6g0..E.
0010 00 1d 6f 9a 00 00 80 11 07 8a c0 a8 03 04 ff ff ..o..... ........
0020 ff ff 05 8b 05 9a 00 09 2f 0b 02 ........ /..
And this is what I sent
0000 ff ff ff ff ff ff 00 13 72 36 67 30 08 00 45 00 ........ r6g0..E.
0010 00 22 8c 51 00 00 80 11 ea cd c0 a8 03 04 ff ff .".Q.... ........
0020 ff ff 06 bc 05 9a 00 0e 9c 8f 30 78 32 66 30 62 ........ ..0x2f0b
|
|
|
|
|
Since you got no error messages..
Gee, im not sure.. could you please post more of your code?
look here for hints.
|
|
|
|
|
I hard coded the value for experimenting, The sample code I'm using is for sending text like requesting a web page from a server, and I think I need to send hex code, so I'm going to try and figure out how to send data in a different format. I think the other article in Code Project is correct, in which I need to send 0x02. The szSendBuf is where I place the data.
char* szSendBuf = "STX";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
iResult = getaddrinfo(
"255.255.255.255",
"ms-sql-m",
&hints,
&result
);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
}
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
iResult = send(
ConnectSocket,
szSendBuf,
(int)strlen(szSendBuf),
0
);
|
|
|
|
|
Is that what's in the UDP data portion of the packet (not sure where UDP header ended and your data started)? If so, then you can just make a buffer that has the same exact data, shouldn't be hard just do something like:
const char RequestBuffer[] = {0xff,0xff,...,0x02}
...then just send that... except, if you're not really sure what's being sent, you may not get exactly what you're expecting... there's probably an API that defines the interactions between a "SQL Manager" and other SQL servers. If you're trying to create an application that simulates a manager, you should probably find whatever standard defines those interactions and implement that instead of just trying to blindly copy a data packet.
Good luck.
|
|
|
|
|
I know the basics, 8 bit makes a byte, and so forth, but I can't read the code I posted. I am however getting better at using the ethereal, and highlighting the portions of the transmission, such as data.
The data being sent seems to be just 1 byte, with a value of 02, and is represented as a dot .
I was thinking last night that perhaps instead of sending a char, like you would use to request a web page, I need to send a bytes.
|
|
|
|
|
If the actual data that is being sent is a x02 (hex), then that's what you need to send... looking at your packet, it looks like you have something like "0x2f0b" (as text, not bytes)... that seems like you're accidentally sending the address of your buffer instead of the values contained in it.
|
|
|
|
|
ohhhhhhhhhhh.
I think I'm closer now. I'm sending cc, but I'm suppose to send 20.
I manually altered the buffer size in send to 1, instead of using (int)strlen(sendbuf)
So I think I'm building the data too big.
This is a lot to learn, but I need to learn it. here's what I'm using now, I think I'm on the right track
BOOL CA_SQLServer_Scan::_socket_Broadcast_SQLServers( void )
{
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 1434
int iResult;
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
int recvbuflen = DEFAULT_BUFLEN;
char recvbuf[DEFAULT_BUFLEN] = "";
char mac[5];
char sendbuf[1];
memset(sendbuf, 0x00, sizeof(sendbuf));
strcpy(sendbuf, "");
sprintf(sendbuf+strlen(sendbuf), "", strlen(sendbuf), sendbuf);
memcpy(sendbuf+strlen(sendbuf), mac, 5);
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error: %d\n", iResult);
return 1;
}
ConnectSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ConnectSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "255.255.255.255" );
clientService.sin_port = htons( DEFAULT_PORT );
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
if (iResult == SOCKET_ERROR) {
wprintf(L"connect failed with error: %d\n", WSAGetLastError() );
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
iResult = send( ConnectSocket, sendbuf, 1, 0 );
if (iResult == SOCKET_ERROR) {
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %d\n", iResult);
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
wprintf(L"shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
wprintf(L"Bytes received: %d\n", iResult);
else if ( iResult == 0 )
wprintf(L"Connection closed\n");
else
wprintf(L"recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"close failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
WSACleanup();
return TRUE;
}
What I'm trying to copy
0000 ff ff ff ff ff ff 00 13 72 36 67 30 08 00 45 00 ........ r6g0..E.
0010 00 1d 6f 9a 00 00 80 11 07 8a c0 a8 03 04 ff ff ..o..... ........
0020 ff ff 05 8b 05 9a 00 09 2f 0b 02 ........ /..
What I got back with the posted code
0000 ff ff ff ff ff ff 00 13 72 36 67 30 08 00 45 00 ........ r6g0..E.
0010 00 1d 94 48 00 00 80 11 e2 db c0 a8 03 04 ff ff ...H.... ........
0020 ff ff 12 32 05 9a 00 09 58 63 cc ...2.... Xc.
|
|
|
|
|
why not just... ???
char sendbuf[] = {0x02};
|
|
|
|
|
I tried and sent the actual string 0x02
|
|
|
|
|
I took out the memset and did the straight char, yes it works and it's faster,
OK, feel stupid but I did not fully understand the process. I tried it earlier, but got some kind of Int error.
Do you know anything about the receive side of the socket? it just sits there and never closes, or transfer data to the receive buffer.
|
|
|
|
|
I don't remember exactly off hand what it should do... but since UDP is essentially connectionless (meaning no hand-shaking between server and client), I imagine the socket has to be closed explicitly by the application.
jkirkerx wrote: or transfer data to the receive buffer.
Don't know exactly what you mean by that.
|
|
|
|
|
I took a generic winsock2 sample code and modified it for UDP broadcast. I have come to the same conclusion, in which the socket will never close, because it's not an single machine to machine connection, in which the other side will never send the symbol saying it's done, or simply close it's port.
I just need to figure out how to capture the return data.
Not sure if I need 2 sockets, one to just send the broadcast, and the other to just listen. If I do that, I'm afraid the listening socket will cause my code to stop, and I won't be able do anything until the socket closes.
|
|
|
|
|
Finally figured it out, and got back packets from all the SQL Servers on the network, complete with all the information I need.
So now I know how to send a STX command to SQL Browser, to start a conversation. It's sort of like a modem command.
Now I have to figure out how and when to release the receive side of the socket, and only capture the packets that I need.
So the SendMessage, which is a char string, has to be set with memset, in order to send just the byte.
|
|
|
|
|
A char* is not necessarily a string... it's just a char pointer... in network programming, character buffers are commonly used to hold the data being transferred to/from a socket because of the size of a char is one byte. It's just convenient to use that since it's the smallest data element used/transferred.
|
|
|
|
|
To make my code more readable I'm trying to use a set of defined values in a switch statement. Basically I have a 4 CHAR tag I want to convert to a DWORD.
#define _makeTag(x) ((#x[0] << 24) | (#x[1] << 16) | (#x[2] << 8) | #x[3])
#define tag_cmap _makeTag(cmap)
In the above I have a 4 CHAR string "cmap" which in DWORD form should be 0x636d6170. However when using in a switch statement the compiler complains that it's not constant. The commented line works, however I believe it to be unreadable.
Any suggestions?
My previous method was to use a union but that required a loop over all the values, hence slow code.
Waldermort
|
|
|
|
|
no, it's not const. Because it's not a compile-time operation. You're accessing a memory location. If you were to look at the generated C-code, it would look like the following:
(("cmap"[0] << 24) | ("cmap"[1] << 16) | ("cmap"[2] << 8) | ("cmap"[3]))
So, it's runtime code, *not* a constant.
You could try assigning it to a constant though, as follows:
const tag_cmap = _makeTag(cmap);
instead of the
#define tag_cmap
If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams You must accept one of two basic premises: Either we are alone in the universe, or we are not alone in the universe. And either way, the implications are staggering” - Wernher von Braun
|
|
|
|
|
ahmed zahmed wrote: You're accessing a memory location.
LOL, That thought hit me right after posting the message.
Compiler still complains when assigning to a const.
I've decided to go with my first method but instead to use _makeTag('c','m','a','p') directly in the switch.
Thanks again.
Waldermort
|
|
|
|
|
It turns out that you do not need a macro at all to do what you want.
Try this -
DWORD d = 'cmap';
Please note the single quotation marks.
|
|
|
|
|
Nice!
Out of curiosity what compiler are you using? I think I may have tried that back on VS8 but with errors.
Waldermort
|
|
|
|
|
I currently use VS2010, but I'm sure this works in older compilers, because this type of assignment is used to tag memory allocations in kernel mode code from ages ago.
|
|
|
|
|
WalderMort wrote: Any suggestions?
Why, yes: don't use macros, they make your code unreadable
No, seriously: using macros is dangerous, with very few exceptions. Regarding your example, your choice of symbol alone already breaks two common safeguards against macro problems:
1. Do not ever use a symbol with starting '_'! This is what the system libraries use internaly to prevent name clashes with any symbols the programmer may define! The problem with name clashes and macros is that macros clash silently, and may break system libraries, resulting in very hard to trace runtime errors (or compiler error,s, if you're lucky)
2. Use capital letters for symbols denoting const or #define symbols. This, also, has to do with preventing name clashes. It may seem overkill, but better be safe than sorry.
I've spent many, many weeks hunting down errors caused my macro name clashes caused by other people's code (and in some cases even by MS #defines!). Do yourself (and everyone else) a favor and don't add to that misery!
|
|
|
|
|