| Profil de Libin绿色家园PhotosBlogListes | Aide |
|
16 août objcopy工具使用指南objcopy Utility objcopy [ -F bfdname | --target=bfdname ] [ -I bfdname | --input-target=bfdname ] [ -O bfdname | --output-target= bfdname ] [ -S | --strip-all ] [ -g | --strip-debug ] [ -K symbolname | --keep-symbol= symbolname ] [ -N symbolname | --strip-symbol= symbolname ] [ -L symbolname | --localize-symbol= symbolname ] [ -W symbolname | --weaken-symbol= symbolname ] [ -x | --discard-all ] [ -X | --discard-locals ] [ -b byte | --byte= byte ] [ -i interleave | --interleave= interleave ] [ -R sectionname | --remove-section= sectionname ] [ -p | --preserve-dates ] [ --debugging ] [ --gap-fill= val ] [ --pad-to= address ] [ --set-start= val ] [ --adjust-start= incr ] [ --change-address= incr ] [ --change-section-address= section{=,+,-} val ] [ --change-warnings ] [ --no-change-warnings ] [ --set-section-flags= section= flags ] [ --add-section= sectionname= filename ] [ --change-leading char ] [--remove-leading-char ] [ --weaken ] [ -v | --verbose ] [ -V | --version ] [ --help ] input-file [ outfile ]
GNU实用工具程序objcopy的作用是拷贝一个目标文件的内容到另一个目标文件中。Objcopy使用GNU BFD库去读或写目标文件。Objcopy可以使用不同于源目标文件的格式来写目的目标文件(也即是说可以将一种格式的目标文件转换成另一种格式的目标文件)。通过以上命令行选项可以控制Objcopy的具体操作。 input-file -I bfdname -O bfdname -F bfdname -R sectionname -S -g --strip-undeeded -K symbolname -N symbolname -L symbolname -W symbolname -x -X -b byte -i interleave -p [ --debugging ] --pad-to= address --set-start= val --change-start = incr --change-addresses incr 通过加上一个值incr,改变所有段的VMA(Virtual Memory Address运行时地址)和LMA(Load Memory Address装载地址),以及起始地址。某些目标文件格式不允许随便更改段的地址。
--change-section-address section{=,+,-} val --change-section-lma section{=,+,-} val --change-section-vma section{=,+,-} val --change-warnings --no-chagne-warnings --set-section-flags section=flags --add-section sectionname=filename --change-leading-char --remove-leading-char --weaken -V -v --help 关于GNU ld和ld脚本
9 août VcExtend工具前 言 VcExtend 扩展了VC6.0的功能,包括函数体批生成、数据接口自动生成,注释可隐可现,注释自动生成文档等功能,可以大大提高VC的工作效率。 VcExtend使用VC60的扩展宏接口,采用VBScript编写,使用起来跟VC本身的命令几乎没有区别。VcExtend完全公开源代码,可以无偿使用和修改。 可以到http://www.mmmnn.com/";>http://www.mmmnn.com下载VcExtend. 下边介绍几个主要的命令: 建立新类:生成干净清爽的类框架,代码模板可自由修改。 代码整理:为函数声明生成函数体,为成员变量生成读写接口(包括声明和实现),将函数体按声明的顺序重排序。这些操作一次性完成,无论你是新设计一个类还是修改一个类,这个命令都会工作得很好。 注释:生成注释模板,注释可隐藏,函数体可调出头文件写的函数注释进行阅读和修改。注释自动生成类似于MSDN的文档。文档数据采用XML文件存储,你可以按照自己的喜好定义显示格式。 注释批处理:显示/隐藏全部详细注释,显示/隐藏注释摘要,自动为数据接口函数生成注释,文档整理理。
Intelligent Screen Saver using OpenCV
IntroductionIt is a utility to control screen saver using human face detection. Human face detection is performed using OpenCV Haar-Cascade method. The software is primarily a daemon that resides in your system tray and keeps observing the input from a webcam to analyze if the user is no longer in view. Currently two angles are supported namely frontal pose and profile pose. BackgroundThe idea of an intelligent screen saver is not new. In past it was not achievable because of the accuracy problems with computer vision algorithms and computation power of computers. OpenCV (open source computer vision library) has an implementation of the object detection algorithm suggested originally by Paul Viola. I have adopted from the face detection sample that comes with this library and have used the cascades files that come with it. Using the codeFacedetection is performed by a mix-mode dll, i.e. it uses unmanaged code to perform face detection and provides a managed wrapper. This dll, hence can now be called from any CLR enabled language (C#, VB.NET etc.). This dll expects a managed System.Drawing.Image object and performs face detection. This managed System.Drawing.Image object is taken from the ctlDxCam library (a custom library built from code posted on an article on codeproject.com, it can capture frames from a webcam as System.Drawing.Image objects) which captures video frames from a webcam. Screensaver is controlled by a class that uses borrowed code from another article on codeproject.com. Please consult references section for details. // On the first thread we perform polling for face detection
CommonVariables.FaceDetected = (faceLocator.WrapDetectFaces(LatestFrame)>0);
// On the second thread we evaluate conditions to trigger screen saver
private void Run()
{
bool IsScreenSaverRunning;
while(KeepRunning)
{
//check if screen saver is currently active
IsScreenSaverRunning = ScreenSaverHandler.IsScreenSaverRunning();
//if last captured frame has not been evaluated
if(!CommonVariables.IsConsumed)
{
//was faces detected in the last polled frame
if(CommonVariables.FaceDetected)
{
CommonVariables.VoteCount = 0;
//yes face was detected, kill screen saver if running
if(IsScreenSaverRunning)
ScreenSaverHandler.StopScreenSaver();
}
else if(!IsScreenSaverRunning)
{
//face was not detected, screen saver isnt running either
//collect votes of no_face_detected
CommonVariables.VoteCount++;
//if votes exceed tolerated amount of no_face detected condition
if(CommonVariables.VoteCount >= CommonVariables.MinVoteRequired)
{
//reset votescount and launch screen saver
CommonVariables.VoteCount = 0;
ScreenSaverHandler.LaunchScreenSaver();
}
}
}
if(IsScreenSaverRunning)
Thread.Sleep(1000); //shorter polling timer
else //longer polling timer
Thread.Sleep(CommonVariables.PollingTimer);
}
}
The source code performs polling on the camera input and evaluates the captured frame at desired interval of time. For each frame that does not have a face in it, a counter (VoteCount) is incremented. After a specified number of such votes, screen saver is launched. If the polling timer is set to 5 seconds and required votes is set to 2, then if a person leaves his seat, screen saver will start running in approximately (5*2) 10 seconds. Points of InterestThis source code demonstrates an interesting concept to use OpenCV from managed code (C#, VB.NET, Managed VC++.NET). The algorithm of face detection is very robust but still has its limitations. False detection of the algorithm can be adjusted by setting the light condition of the environment and camera position etc. User can select whether he wants frontal face detection or profile face detection and hence place camera in respective angles. References
Interface DetectionContentsIntroductionIn any C++ program, calling a function that hasn't been declared obviously leads to a compilation error. Detecting the interface of a class lets the programmer check the presence of a given public member function or data without generating such errors, allowing him to specify a different behavior when the member doesn't exist. Interface detection doesn't use any inheritance properties and, as such, offers new cleaner and safer solutions. This article describes a way to implement such detection facilities, by exploring and explaining some advanced C++ topics. Motivating exampleSuppose we want to write a container class that provides all standard container operations such as UsageMetaContainer< int, std::vector > myContainer1;
MetaContainer< double, std::list > myContainer2;
MetaContainer< int, UserContainer > myContainer3;
The programmer can then choose the underlying container to tune performance. For example, if a lot of insertions in the middle of the collection are performed,
void MetaContainer::Remove(...)
{
...
m_UnderlyingContainer.remove(...);
...
}
If the underlying container class, such as Required technical backgroundBefore explaining the solution, some key C++ concepts used in the interface detection implementation must be reviewed. In this chapter, the following topics are tackled in a very concise way:
If you already know all of those concepts, you may jump directly to the next chapter. Pointers to memberIntroductionPointers to members can be divided into 4 categories:
Example: struct MyClass
{
void MF (int); // non static Member Function
int MD; // non static Data Member
static void Static_MF (int); // static Member Function
static int Static_MD; // static Data Member
}
We'll refer to those 4 member declarations in the rest of the chapter. Syntax of pointers to memberPointers to each of the aforementioned members adopt a homogeneous syntax:
Because the syntax of pointers to members includes the name of a class, such pointers can be dependent names. In contrast, pointers to ordinary functions or data can't. A dependent name is a name that depends on a template parameter. For example: template< class T >
void f ()
{
...
pf = &T::MF; // pointer dependent on the T parameter
}
The name dependence property plays an important role in our solution. Type of pointers to membersType of pointers to member functionsThe pointers to member functions have the following types:
Notice how the type of a pointer to a static member function can be misleading. A non-static member function follows a specific convention: it adds an implicit parameter that accepts a pointer to an object. A static member function doesn't apply to an object and doesn't have an implicit object parameter. A pointer to such a function has the same type as an ordinary function pointer. 1 The important point here is that pointers to non-static and static member functions have different types that are incompatible with each other. Type of pointers to data membersTypes of pointers to static and non-static data members follow the same syntax differences as their function counterparts:
The types of pointers to static and non-static members are again different and incompatible. This is because the latter is associated with an object and thus contains an offset rather than an address. Pointers to member as non-type template argumentsA pointer to a member can be a non-type template argument. The syntax is straightforward. As an example, we'll use each of the types of pointers we saw above as template parameters: template < void (MyClass::*)(int) >
void f1 () {}
template < void (*)(int) >
void f2 () {}
template < int MyClass::* >
void f3 () {}
template < int* >
void f4 () {}
f1 < &MyClass::MF > (); // ok
f1 < &MyClass::Static_MF > (); // Error: type mismatch
f2 < &MyClass::Static_MF > (); // ok
A pointer to a member as a template argument must be of the exact type specified in the template declaration. There is no possible conversion. SFINAESFINAE, an acronym for "Substitution Failure Is Not An Error," is a principle that works during function overload resolution as follows: if the instantiation of a template function produces an invalid parameter or return type, the compiler silently removes the ill-formed function instantiation from the overload resolution set. For example: struct Test
{
typedef int Type;
};
template < typename T >
void f( typename T::Type ) {} // definition #1
template < typename T >
void f( T ) {} // definition #2
f< Test > ( 10 ); //call #1
f< int > ( 10 ); //call #2 without error thanks to SFINAE
Without SFINAE, the second call would have generated an error during the substitution of the template parameter in #1. The result of the instantiation of #1 from the second call is: Interface detection implementationMember function detectionAs pointed out in the introduction, using the identifier of an undeclared function generates a compilation error. Checking if a function exists logically necessitates the use of its identifier, as we don't use any inheritance property or any extra information. We must find a mechanism that doesn't generate an error when the identifier refers to an undeclared function. SFINAE fits well in this task. Since member function pointers can be dependent names, we could use the SFINAE principle on them. However, SFINAE is applied to the parameter type or return type of a function. A member function pointer isn't a type and can't be directly used in a function signature. To overcome this, the function pointer is used as a template argument: template < void (MyClass::*)() >
struct TestNonStatic { };
With the template < class T >
TestNonStatic<&T::foo> Test( );
SFINAE doesn't generate an error as long as there is another function in the overload resolution set. We need to declare a function that will be used as a "fallback" when the member function -- template < class T >
void Test( ... );
A function with the ellipsis parameter is always the lowest priority function in an overload resolution set, isn't it? The C++ standard says yes, Visual C++ 8 says yes, GCC says no for our case.
2 The alternative solution is to simply use the The next step is to find a way of knowing at compile-time which // Return types for sizeof
typedef char NotFound;
struct NonStaticFound { char x[2]; };
struct StaticFound { char x[3]; };
// Test Structures for SFINAE
template < void (MyClass::*)() >
struct TestNonStatic ;
template < void (*)() >
struct TestStatic ;
// Overload functions
template < class T >
StaticFound
Test( TestStatic< &T::foo >* );
template < class T >
NonStaticFound
Test( TestNonStatic< &T::foo >* );
template < class T >
NotFound
Test( ... );
check_presence = sizeof( Test< MyClass >( 0 ) );
The final step is to wrap the whole mechanism into a reusable class from which you can specify the class and function signature to test. However, the identifier of a function -- in the above example, Last consideration: what about constant member functions? The above code doesn't detect them. If the user specifies a constant member signature to the reusable detector class, it won't compile because as we use the given function signature to construct the template parameter of the
Adding a test structure with a constant member signature to the detector class seems to deal with the problem: template < void (MyClass::*)() const >
struct TestNonStaticConst ;
Simply putting together the functions // Test Structures for SFINAE
template < void (MyClass::*)() >
struct TestNonStatic ;
template < void (*)() >
struct TestStatic ;
template < void (T::*)() const >
struct TestNonStaticConst ;
// Overloaded functions
template < class U >
NonStaticFound
Test( TestNonStatic< &U::aff >*, ... );
template < class U >
NonStaticFound
Test( TestNonStaticConst< &U::aff >*, int );
template < class U>
StaticFound
Test( TestStatic< &U::aff >*, int );
template < class U >
NotFound
Test( ... );
check_presence = sizeof( Test( 0,0 ) );
Data member detectionAfter seeing how to implement member function detection, doing the same for data members is straightforward. It is, in fact, easier since we don't have to care about the constant members problem. The only changes concern the template parameter of the
// Return types for sizeof
typedef char NotFound;
struct NonStaticFound { char x[2]; };
struct StaticFound { char x[3]; };
// Test Structures for SFINAE
template < int MyClass::* > // change 1 of 2
struct TestNonStatic ;
template < int * > // change 2 of 2
struct TestStatic ;
// Overload functions
template < class T >
StaticFound
Test( TestStatic< &T::foo >* );
template < class T >
NonStaticFound
Test( TestNonStatic< &T::foo >* );
template < class T >
NotFound
Test( ... );
Known limitations and problemsLimitations of the current interface detector fall into 2 categories:
Compilation problemsThere are two kinds of compilations errors:
Standard compilation errorsAccess checking errorOnly public members are concerned by the interface detector. However, if a function given to the detector happens to exist in a private or protected section of the class, the compiler will issue an "access denied" error. Because class member access checking comes after name look-up and overload resolution, SFINAE won't silence the error. Compiler-specific errorsThis section lists non-standard errors generated by the latest C++ compilers. Of course, earlier compilers that don't fully support templates -- such as Visual C++ 6 -- are likely to give some errors, but they aren't listed here. The following table represents the detection capabilities and bugs from the currently tested compilers:
Visual C++ data member detection bugIn Visual C++, a dependent name consisting of a pointer to a static or non-static data member gives an error during the substitution if the data member isn't of a built-in type. struct Y {};
struct X
{
Y a;
};
template < Y X::* >
struct Test ;
template < class T >
void f (Test< &T::a >*) {}
f< X >(0); // error on Visual c++ 8
The above code is well-formed according to the C++ standard. GCC and Comeau compile it, but not Visual C++. It leads to a pernicious effect in our interface detector since the data member detection is included in a SFINAE mechanism and therefore won't generate errors. This leads to the fallacious behavior of returning the
Design limitationsExact signatureThe interface detector checks the exact signature with no conversion. For example, if you want to check the presence of Semantic discrepancyThe second limitation is the possible semantic difference between the detected function and the actual use of the function. For instance, in biology, some cells can be cloned. I can check this "clonable" capability by detecting whether the object contains a
UsageThe utilization of the provided interface detector relies on 4 macros:
The first two macros are needed to construct the detector from the identifier of the function or the data to be detected. This is the first step before proceeding to the actual detection. For example, if I want to detect the function
CREATE_FUNCTION_DETECTOR(foo);
Note that once the detector for // detection: int foo (double, int)
DETECT_FUNCTION ( MyClass, int, foo, (double, int) )
// detection: const int bar
DETECT_DATA ( MyClass, const int, bar )
// detection: void foo()
DETECT FUNCTION ( MyClass, void, foo, () )
The
All of those constants belong to the struct X
{
void Print()
{
std::cout << "X Print" << std::endl ;
}
};
struct Y
{};
First, we need to construct the detector: #include "Detector.h"
CREATE_FUNCTION_DETECTOR(Print);
Second, we have to define a structure that will be used to select a different behavior according to the presence of the function. The first template parameter of the structure will be used to hold the result of the template < int, class T >
struct Select
{
static void Print ( T obj )
{
obj.Print();
}
};
template < class T >
struct Select < Detector::NOT_FOUND , T >
{
static void Print ( ... )
{
std::cout << "No Print function" << std::endl;
}
};
// Helper function
template < class T >
void PrintHelper( T a )
{
Select< DETECT_FUNCTION ( T, void, Print, () ) , T >::Print( a );
}
Now we can safely call X a;
Y b;
PrintHelper(a); // "X Print"
PrintHelper(b); // "No Print function"
The process of selecting the correct behavior is done at compile-time. A whole class interface can be checked at once. For example, let's say that any object that can fly and quack is a duck. To know whether a class represents a duck according to this definition, we can check if both the
DETECT_FUNCTION( Class, void, Fly, () ) &
DETECT_FUNCTION( Class, void, Quack, () )
A better way to do a multiple function or data check is to define a macro like this: #define DUCK_INTERFACE( Class ) \
DETECT_FUNCTION( Class, void, Fly, () ) & \
DETECT_FUNCTION( Class, void, Quack, () )
This way, a simple and understandable expression can be used and reused to detect whether a class is a duck. Now here's the solution of the "motivating example," i.e. "How can we know whether the container class has a CREATE_FUNCTION_DETECTOR(remove);
template < class T, template < class , class > class Container >
int HasRemove ()
{
return DETECT_FUNCTION( Container< T >, void, remove , (const T& ) );
}
HasRemove< int, std::vector >(); // NOT_FOUND
HasRemove< int, std::list >(); // NON_STATIC_FUNCTION
ConclusionInterface detection brings unique solutions to specific problems. It can also be used to support any duck typing 3 design -- such as policy-based design -- resulting in a safer, cleaner and extended design. One might also check the BCCL 4 that makes this kind of design more robust. The interface detection implementation heavily relies on many advanced C++ techniques, especially template ones. As such, it has some inevitable downsides: code complexity, support only by the latest compilers, difficulty in tracking bugs exhaustively and homogeneously amongst compilers, etc. Fortunately, the next C++ standard 5 should ease the programming of such template solutions. Notes[1] The compiler, for the purpose of overload resolution only, assumes that a static member function accepts an implicit object parameter.[2] GCC considers that 2 functions share the same priority if one of them has the same declaration as the other with the addition of an ellipsis at the end of its parameter list [3] In a duck typing system, the value of an object determines the object's behavior. C++, through the use of templates, implements a static form of duck typing. Duck typing on Wikipedia [4] BCCL: Boost Concept Check Library [5] Bjarne Stroustrup, A Brief Look at C++0x Wake On LAN (WOL)
Already read it all? use: Update History
Before you startYou'll need a background of computers, Networks, Socket Programming, VC++(MFC) before reading this article. IntroductionThe problem is to find a way to turn on other machines in a local area network, from our machine which might or might not be the Server. The Solution is known as Wake On LAN. WakeOnLan (or for short just WOL) is a mechanism with which a network Interface Card (NIC) could turn a machine on by receiving a special packet through the LAN. Acknowledgements
How does it workWhile your computer is Turned Off, The Network Interface Card remains on and looks forward to hearing a message! More accurately, a packet does, which is called a magic packet. Whenever the card receives information, a magic packet tries to switch on the computer. This packet must contain a certain byte-sequence, but can be encapsulated in any kind of packet (IPX, IP, anything). So the mechanism relies on the Hardware's ability, and that's why we need some ingredients! Hardware requirementsBoth motherboard and NIC must support WOL. If you have a built-in NIC with WOL support, it's almost done! But many PCI NICs come with a connector and a wire, which has to be connected to the motherboard's WOL connector. After these, your power supply and OS must support WOL. And finally, you should enable Wake-On-LAN in your systems BIOS (or whatever called). That's it. Magic PacketI'm not sure, but it seems that the name comes from AMD. I did not do a search but José Pedro Oliveira (second link above) says that there is more documentation about the protocol in their web site. As I mentioned above, you need to send a special packet in your LAN network, so that the remote computer will receive it and wake up. This so-called Magic packet consists of the following parts:
Magic Packet(With Secure On Password)(This part added on an update on: 2005/09/03. Note that 'PowerOn' sample has been updated in all downloads either. [as well as executables!]) Some clients require a password in the packet to be turned on, otherwise they simply won't! This password is also known as SecureOn, and will be attached at the end of the packet. In this case, a packet will look something like this:
So we have six cells, each capable of saving an integer number between 0 and 255(Just like MAC bytes). What's MAC address and how to obtain itMAC stands for Media Access Control, and is a unique 48-bit (6 Bytes) hexadecimal number assigned to a NIC when it is manufactured. And it is unique; you'll not find two NICs with the same MAC Address in the world. The first three octets (24 bits) are known as the Organizationally Unique Identifier (OUI) and identifies its manufacturer. It means the MAC address of all cards of a company that say X start with a particular fixed number at the beginning. I'm not sure if this address is just assigned to Ethernet Cards or any other types of network Interface or equipment. This address is typically written as six colon/dash-separated hexadecimal numbers. In Microsoft Windows (98 SE and above, perhaps winipcfg.exe ) there's a tool called ipconfig.exe which could be used to obtain a MAC address. Ipconfig refers to this address as Physical Address . In order to see the MAC address of your NIC, just type this in the command line: ipconfig /all. There are several alternative ways of finding a MAC address, like looking for an ARP table (if any exists! or it has any entries), ifconfig (just in Linux), netstat, GetMAC (XP), all of which are enough to be a topic for a new article!
So let's come back to our subject! For example, and according to the above figure, you should send a packet like : ff-ff-ff-ff-ff-ff 02-00-4c-4f-4f-50 02-00-4c-4f-4f-50 ... 02-00-4c-4f-4f-50 to the computer with the above MAC address to turn it on. But the question is: "How to obtain this address in your app". To be honest, before Googling the web I tried to do a disassembly on ipconfig.exe and I found // Allocate information for NIC
IP_ADAPTER_INFO AdapterInfo;
// Save memory size of buffer
DWORD dwBufLen = sizeof(AdapterInfo);
// Call GetAdapterInfo
DWORD dwStatus = GetAdaptersInfo(&AdapterInfo,&dwBufLen);
// Verify return value is valid
ASSERT(dwStatus == ERROR_SUCCESS);
// Contains pointer to current adapter info
PIP_ADAPTER_INFO pAdapterInfo = (&AdapterInfo);
pAdapterInfo->Address;//Is the MAC Address of our NIC
//for a more acurate implementation and my modifications,
//Please see the demo project.
We have the address, but still have the problem of sending data to a switched off computer! The solution is to broadcast a UDP packet. Did this already? Add a new feature to your local network project: Turn On All Network Machines . Did not do this already? Take a look at the demo project -PowerOn. Remote MAC finder & ARPAfter publishing this article on 2005/08/29, I found out that most readers wanted two major features:
Thanks to Mr. Tupack Mansur, and other readers who created this temptation in my heart! (See discussion and comments below) Based on the above demands, I started another project: Remote MAC finder (third project to download), which is designed to find the MAC of a computer which we have it's IP or Host Name. Why I didn't upgrade old PowerOn project? Just to keep it simple. I could do something with the second request if I was IEEE! The problem is that to send a packet over the internet, routers need an IP address, but a turned off machine has not need one, so there is not any way to address a remote machine. As far as I know, routers will remove broadcast packets from the Internet, so don't think about it. One way would be to send a WOL packet to your LAN router which might or might not support this. An internally broadcast address like 192.168.1.255 must forwarded. Two other methods might be using telnet (wol up) directly or indirectly by 'Remote Desktop' to an always on machine and turning on others from there(Thanks to an anonymous reader who described his solution.). Remote MAC Finder works based on ARP. If you already know ARP protocol, you can ignore this next part, but since I'm still a beginner in Networks, Programming ,and even worse, self-educated (my university did not teach me these things), there might be mistakes and it will be greatly appreciated if you help to correct me. Thank you. ARPARP(RFC 826) stands for Address Resolution Protocol. Although all host machines and network tools use unique IP addresses, but any IP packet will cross the first layer of TCP/IP model before going to channel. This first layer is called the Network Interface Layer. The Network Interface layer will work just with a physical address known as MAC. Any IP packet containing an IP address will be placed in a Data Field(Payload) of the first layer frames and a header containing a MAC address of the destination will be added later. In other words, each machine is a network which has a packet to send to another, and should know both destination's MAC and IP addresses. Network interfaces will also recognize packets on the net, containing their MAC address and will take them for further processing. But what if a computer in a network doesn't have its peer MAC address? This is what ARP was created for. The duty of ARP is to broadcast a packet over a network. This packet actually asks: "Any one whose IP address is (say) ' 192.168.1.5', What is it's MAC address?". Broadcasted packets will be received by all Network machines, and as soon as a machine sees its own IP in the packet will send a reply to the requester and places its MAC address in the reply packet. In order to increase ARP speed, each time a machine finds a MAC address corresponding to an IP, the protocol will save these numbers in a table in main memory. The table is called ARP cache. So one way of finding the MAC of a remote computer is by enumerating IP's from this table and when a match is found, taking it's MAC. But the problem is that the life of this table (ARP Cache) is too small (we should exclude routers, I guess). (My test on Windows XP SP1 was about 2 Minutes!) Some commands will update entries of this table. I found that the function
But this process is not always reliable! The reason is that with this mechanism, an attack could be shaped :ARP Spoofing! I don't know much a lot about how it works, but it might be a good idea for an administrator to think about it! That's why I say it's not always reliable. Using the code(added upon update: I did not have the chance to test the new uploaded 'PowerOn' to see how it works with a password. It would be appreciated if anyone does can tell if his/her test was successful. Thank you. I did not provide any C++ classes, because I didn't want to hide such easy stuff from readers and write a class for one function! There are two demos included in this article.
In the PowerOn demo I tried to turn on a computer in our LAN network, using the mechanism I described above. The job is completed in two functions The
//Socket to send magic packet
CAsyncSocket s;
//Buffer for packet
BYTE magicP[102];
...
//Fill in magic packet with 102 Bytes of data
//Header
//fill 6 Bytes with 0xFF
for (int i=0;i<6;i++)
magicP[i] = 0xff;
//First 6 bytes (these must be repeated!!)
//fill bytes 6-12
for (i=0;i<6;i++) {
//Get 2 charachters from mac address and convert it to int to fill
//magic packet
magicP[i+6] = HexStrToInt(macAddr.Mid(i*2,2));
}
//fill remaining 90 bytes (15 time repeat)
for (i=0;i<15;i++) memcpy(&magicP[(i+2)*6],&magicP[6],6);
...
//Broadcast Magic Packet, Hope appropriate NIC will take it ;)
s.SendTo(magicP,102,atol(m_port));
MAC FinderAt first I thought I couldn't add the following project, but thought more and decided to do it because you might want to find a MAC automatically, and probably give the found address to your peer (TCP socket) application in a LAN, and use it later! Whatever you want to do, this might be helpful. I used Mr. Khalid Shaikh's code, but his code was not 'compileable' in my VC++ 6.0, so I found the appropriate DLL where the function had been located and used MSDN to reproduce the needed structures (hope this is not a copyright problem) and then used a pointer to the function and
Most Interesting part of the storyThere was a very interesting point I encountered, while working with MACs! Look at the above MAC address (in the figure). It's the MAC of a Microsoft loopback adapter. Since I do not have 2 (or more) computers, I tested my network applications (bot PowerOn) using this NIC. Look carefully at its MAC address:02-00-4c-4f-4f-50, and try converting numbers to characters using ASCII standard. What do you see? : 02= :) 00= blank 4C= L 4F= O 50= P = > Microsoft Loop back Adapter's MAC address is :) LOOP Who decided on these numbers, that's the mystery! GLUT Window Template
Note: This article has been reposted at the author's request after the original was deleted at the author's request. ContentsIntroductionThis program sets up a platform-independent OpenGL window using the GLUT library. What is OpenGL?OpenGL is the most widely used application programming interface (API) for developing portable 2D and 3D graphics applications. It was originally developed in 1992 by Silicon Graphics and is currently controlled and maintained by the OpenGL ARB (Architecture Review Board), which has become a part of the Khronos Group in 2006. ARB representatives include SGI, Microsoft, Apple, nVidia, ATI, Intel, id Software (famous for creating DOOM and QUAKE), and 3D Labs. OpenGL has become an industry standard and a very popular API for its ease of use, portability, stability and rich documentation. According to OpenGL.org, OpenGL is the only truly open, vendor-neutral, multiplatform graphics standard. OpenGL 2.1 is the latest version of OpenGL and was released on August 2, 2006. OpenGL 3.0 is currently under development and will run specifically on hardware born after November 8th, 2006. Why use GLUT?OpenGL is a window system independent graphics library. This means that it doesn't handle window system operations that are specific to the Operating System. The reason for this is to make OpenGL portable on even new platforms. Creating a rendering window and handling events is left to the native window system to define. The OpenGL Utility Toolkit (GLUT) is intended to fill this gap, and thus provides developers with a window system independent API for OpenGL programs. GLUT supports the following functionality:
It is important to note that GLUT is not a fully-featured windowing toolkit. It is mostly used for learning OpenGL and developing simple OpenGL programs. GLUT is simple, easy and small. The GLUT library has C, C++, FORTRAN and Ada programming bindings. It is portable to nearly all OpenGL implementations for the X Window System and Windows. The latest stable GLUT version is 3.6; the 3.7 version is currently in Beta phase. Why have a GLUT window template?Knowing that OpenGL is an API intended for graphical applications, it is very clear that a window is always required to render the graphical objects. To avoid having to write the same code every time you want to create a graphical application using OpenGL, this program code can be used as a template to get you directly started with what matters to you in the program. The OpenGL GLUT window template has the following properties:
UsageRunning the programIn order to run the program, 3 dynamic link libraries (DLLs) are required: opengl32.dll, glu32.dll and glut32.dll. The opengl32.dll and glu32.dll files already come with your Windows OS and are found in the system folder. To run the executable, you have to download the glut32.dll and copy it into your system folder. You can find all of the DLL files in the attached ZIP file, GLUT_Window_Template_dll.zip under Visual C++\dll. Compiling the code with Microsoft Visual C++In order to write a C OpenGL application with GLUT using Microsoft Visual Studio on a Windows platform, you need the following files: C header files: GL.h, GLU.h and GLUT.h C LIB files: glui32.lib, opengl32.lib and glut32.lib You can find all of the header and LIB files in the attached ZIP file GLUT_Window_Template_dll.zip under Visual C++\include\GL and Visual C++\lib, respectively. Microsoft Visual C++ 6To use the code under a Visual C++ 6.0 environment, perform the following steps:
Using the codeThe source code is intended to be used as a template for your OpenGL applications. To use it in your new application, you can simply rename the C file and add it to your Visual Studio project. Explaining the codeThe header files for GLUT should be included in GLUT programs with the following include directive: #include <GL/glut.h>
There is no need to include InitializationFunctions starting with Below I show each initialization function prototype, its description and how I used it in my program. Connecting to the window systemvoid glutInit(int *argcp, char **argv);
glutInit(&argc, argv);
Setting window sizevoid glutInitWindowSize(int width, int height);
Use // variables representing the window size
int window_width = 240;
int window_height = 240;
// Set the window size
glutInitWindowSize (window_width, window_height);
Setting window positionvoid glutInitWindowPosition(int x, int y);
Use the
// define the window position on screen
int window_x;
int window_y;
//-------------------------------------------------------------------------
// This function sets the window x and y coordinates
// such that the window becomes centered
//-------------------------------------------------------------------------
void centerOnScreen (void)
{
window_x = (glutGet (GLUT_SCREEN_WIDTH) - window_width)/2;
window_y = (glutGet (GLUT_SCREEN_HEIGHT) - window_height)/2;
}
// Set the window position
glutInitWindowPosition (window_x, window_y);
In the code above, I am simply making the window centered on the screen. Setting display modevoid glutInitDisplayMode(unsigned int mode);
The display mode specifies what buffers are to be used in order to render the OpenGL graphics. One may choose more than one mode by using the logical
glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);
To display graphical content on a window, we need to tell GLUT whether to use single buffering or double buffering. In case single buffering is to be used, we need to set the However, Create windowint glutCreateWindow(char *name);
Creates the GLUT window with // variable representing the window title
char *window_title = "GLUT Window Template";
// Create Window
glutCreateWindow (window_title);
After creating the window, you may want to display it in full screen. // Tells whether to display the window full screen or not
// Press Alt + Esc to exit a full screen.
int full_screen = 0;
// View in full screen if the fullscreen flag is on
if (full_screen)
glutFullScreen ();
Set program initial stateThe purpose here is to set some OpenGL properties and initialize any data structures you have in your program. In our case, we need to set the frame buffer clear color to black. This would mean that whenever we want to refresh our graphics, we need to first clear the old drawing with a black canvas and then redraw our new contents. Otherwise, our graphics won't display in the correct manner. //-------------------------------------------------------------------------
// Set OpenGL program initial state.
//-------------------------------------------------------------------------
void init ()
{
// Set the frame buffer clear color to be black.
glClearColor (0.0, 0.0, 0.0, 0.0);
}
The arguments to Set callback functions// Set the callback functions
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutMouseFunc (mouse);
glutMotionFunc (motion);
glutPassiveMotionFunc (pmotion);
glutKeyboardFunc (keyboard);
glutSpecialFunc (special);
These are the callback functions that are mostly used. To see the remaining callback functions that GLUT supports, please refer to the GLUT API Version 3 Reference Manual . glutDisplayFunc//-------------------------------------------------------------------------
// This function is passed to glutDisplayFunc in order to display
// OpenGL contents on the window.
//-------------------------------------------------------------------------
void display (void)
{
// Clear the window or more specifically the frame buffer...
// This happens by replacing all the contents of the frame
// buffer by the clear color (black in our case)
glClear (GL_COLOR_BUFFER_BIT);
// Draw scene
drawObject ();
// Swap contents of backward and forward frame buffers
glutSwapBuffers ();
}
The //-------------------------------------------------------------------------
// Draws our object.
//-------------------------------------------------------------------------
void drawObject ()
{
// Show when are displaying an object
printf ("Displaying object...\n");
// Draw Icosahedron
glutWireIcosahedron ();
}
You will notice the "Displaying object..." message on the command prompt in the following cases:
If you notice this happening in other cases, please let me know. glutReshapeFunc//-------------------------------------------------------------------------
// This function is passed to the glutReshapeFunc and is called
// whenever the window is resized.
//-------------------------------------------------------------------------
void reshape (int w, int h)
{
// Stay updated with the window width and height
window_width = w;
window_height = h;
// Reset viewport
glViewport(0, 0, window_width, window_height);
// Print current width and height on the screen
printf ("Window Width: %d, Window Height: %d.\n",
window_width, window_height);
}
The I am using the glutMouseFuncWhen a user presses and releases a mouse button, two events are generated: one for the press and the other for the release. The //-------------------------------------------------------------------------
// This function is passed to the glutMouseFunc and is called
// whenever the mouse is clicked.
//-------------------------------------------------------------------------
void mouse (int button, int state, int x, int y)
{
switch (button)
{
// Left Button Clicked
case GLUT_LEFT_BUTTON:
switch (state)
{
// Pressed
case GLUT_DOWN:
printf ("Mouse Left Button Pressed (Down)...\n");
break;
// Released
case GLUT_UP:
printf ("Mouse Left Button Released (Up)...\n");
break;
}
break;
// Middle Button clicked
case GLUT_MIDDLE_BUTTON:
switch (state)
{
// Pressed
case GLUT_DOWN:
printf ("Mouse Middle Button Pressed (Down)...\n");
break;
// Released
case GLUT_UP:
printf ("Mouse Middle Button Released (Up)...\n");
break;
}
break;
// Right Button Clicked
case GLUT_RIGHT_BUTTON:
switch (state)
{
// Pressed
case GLUT_DOWN:
printf ("Mouse Right Button Pressed (Down)...\n");
break;
// Released
case GLUT_UP:
printf ("Mouse Right Button Released (Up)...\n");
break;
}
break;
}
}
In order to check if the Shift, Ctrl or Alt key was pressed while the mouse event occured, we can use the glutMotionFuncAs long as the user is moving the mouse while a button is pressed (i.e. dragging), this event will be called continuously. //-------------------------------------------------------------------------
// This function is passed to the glutMotionFunc and is called
// whenever the mouse is dragged.
//-------------------------------------------------------------------------
void motion (int x, int y)
{
// Print the mouse drag position
printf ("Mouse Drag Position: %d, %d.\n", x, y);
}
glutPassiveMotionFuncAs long as the user is moving the mouse while no button is pressed, this event will be called continuously. //-------------------------------------------------------------------------
// This function is passed to the glutPassiveMotionFunc and is called
// whenever the mouse is moved.
//-------------------------------------------------------------------------
void pmotion (int x, int y)
{
// Print mouse move positopn
printf ("Mouse Move Position: %d, %d.\n", x, y);
}
glutKeyboardFuncEach key press generating an ASCII character will generate a keyboard callback. The //-------------------------------------------------------------------------
// This function is passed to the glutKeyboardFunc and is called
// whenever the user hits a key.
//-------------------------------------------------------------------------
void keyboard (unsigned char key, int x, int y)
{
// Print what key the user is hitting
printf ("User is hitting the '%c' key.\n", key);
printf ("ASCII code is %d.\n", key);
switch (key)
{
// User hits A key
case 'a':
break;
// User hits Shift + A key
case 'A':
break;
// User hits Enter
case 13:
printf ("User is hitting the Return key.\n");
break;
// User hits Space
case 32:
printf ("User is hitting the Space key.\n");
break;
// User hits back space
case 8:
printf ("User is hitting the Back Space key.\n");
break;
// User hits ESC key
case 27:
exit (1);
break;
}
glutPostRedisplay ();
}
In order to check if the Shift, Ctrl or Alt key was pressed while the ASCII key was pressed, we can use the glutSpecialFunc//-------------------------------------------------------------------------
// This function is passed to the glutSpecialFunc and is called
// whenever the user hits a special key.
//-------------------------------------------------------------------------
void special (int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_F1 :
printf ("F1 function key.\n");
break;
case GLUT_KEY_F2 :
printf ("F2 function key. \n");
break;
case GLUT_KEY_F3 :
printf ("F3 function key. \n");
break;
case GLUT_KEY_F4 :
printf ("F4 function key. \n");
break;
case GLUT_KEY_F5 :
printf ("F5 function key. \n");
break;
case GLUT_KEY_F6 :
printf ("F6 function key. \n");
break;
case GLUT_KEY_F7 :
printf ("F7 function key. \n");
break;
case GLUT_KEY_F8 :
printf ("F8 function key. \n");
break;
case GLUT_KEY_F9 :
printf ("F9 function key. \n");
break;
case GLUT_KEY_F10 :
printf ("F10 function key. \n");
break;
case GLUT_KEY_F11 :
printf ("F11 function key. \n");
break;
case GLUT_KEY_F12 :
printf ("F12 function key. \n");
break;
case GLUT_KEY_LEFT :
printf ("Left directional key. \n");
break;
case GLUT_KEY_UP :
printf ("Up directional key. \n");
break;
case GLUT_KEY_RIGHT :
printf ("Right directional key. \n");
break;
case GLUT_KEY_DOWN :
printf ("Down directional key. \n");
break;
case GLUT_KEY_PAGE_UP :
printf ("Page up directional key. \n");
break;
case GLUT_KEY_PAGE_DOWN :
printf ("Page down directional key. \n");
break;
case GLUT_KEY_HOME :
printf ("Home directional key. \n");
break;
case GLUT_KEY_END :
printf ("End directional key. \n");
break;
case GLUT_KEY_INSERT :
printf ("Inset directional key. \n");
break;
}
glutPostRedisplay ();
}
Each key press generating a non-ASCII character will generate a special callback. The
Begin event processingvoid glutMainLoop(void);
After a GLUT program has completed initial setup, such as creating windows and menus, GLUT programs enter the GLUT event processing loop by calling ConclusionI think this article can help significantly in getting you started with OpenGL. At the same time, the template can be used to save lots of copy and paste from old projects or the Internet. In case you find this template useful or have suggestions, please let me know. References |
|
|