This is an indicator I am working on. The problem I am having is it doesn't match the same output as my excel file, and I am pretty sure my excel file is correct. If you would like to help me solve this issue just email me at thetfordjw#gmail.com Subject: Excel mql4 please and I will send you the excel file. Otherwise if you have something to add on this web page as to something I am doing wrong would be happy to hear from you. Thanks !
//+------------------------------------------------------------------+
//| JT-Statistics Close GT LT Terminated.mq4 |
//| Copyright 2021,Jon W. Thetford |
//| Email: thetfordjw#gmail.com |
//+------------------------------------------------------------------+
#property version "1.00"
#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int i;
float a,b,c,d,e,f,g,h,j,k;
float aa,bb,cc,dd,ee,ff,gg,hh,jj,kk,ll,mm,nn,oo;
//input float BarsBack = "1000";
input bool FrequencyNumber = True;
input bool FrequencyPercentage = False;
input bool CumulativePercentageOfAllBars = False;
//input bool PercentageOfCustomBarsBack = False;
int OnInit()
{
//--- indicator buffers mapping
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//---
for(i=0;i<Bars; i++)
{
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]<Close[i+4])
{
a=a+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]<Close[i+5])
{
b=b+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]>Close[i+5]&&Close[i+5]<Close[i+6])
{
c=c+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]>Close[i+5]&&Close[i+5]>Close[i+6]&&Close[i+6]<Close[i+7])
{
d=d+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]>Close[i+5]&&Close[i+5]>Close[i+6]&&Close[i+6]>Close[i+7]&&Close[i+7]<Close[i+8])
{
e=e+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]>Close[i+5]&&Close[i+5]>Close[i+6]&&Close[i+6]>Close[i+7]&&Close[i+7]>Close[i+8]&&Close[i+8]<Close[i+9])
{
f=f+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]>Close[i+5]&&Close[i+5]>Close[i+6]&&Close[i+6]>Close[i+7]&&Close[i+7]>Close[i+8]&&Close[i+8]>Close[i+9]&&Close[i+9]<Close[i+10])
{
g=g+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]>Close[i+5]&&Close[i+5]>Close[i+6]&&Close[i+6]>Close[i+7]&&Close[i+7]>Close[i+8]&&Close[i+8]>Close[i+9]&&Close[i+9]>Close[i+10]&&Close[i+10]<Close[i+11])
{
h=h+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]>Close[i+5]&&Close[i+5]>Close[i+6]&&Close[i+6]>Close[i+7]&&Close[i+7]>Close[i+8]&&Close[i+8]>Close[i+9]&&Close[i+9]>Close[i+10]&&Close[i+10]>Close[i+11]&&Close[i+11]<Close[i+12])
{
j=j+1;
}
if(Close[i+1]<Close[i+2]&&Close[i+2]>Close[i+3]&&Close[i+3]>Close[i+4]&&Close[i+4]>Close[i+5]&&Close[i+5]>Close[i+6]&&Close[i+6]>Close[i+7]&&Close[i+7]>Close[i+8]&&Close[i+8]>Close[i+9]&&Close[i+9]>Close[i+10]&&Close[i+10]>Close[i+11]&&Close[i+11]>Close[i+12]&&Close[i+12]<Close[i+13])
{
k=k+1;
}
//LESS THAN Close[1]<Close[2]
//1
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]>Close[i+4])
{
aa=aa+1;
}
//2
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]>Close[i+5])
{
bb=bb+1;
}
//3
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]>Close[i+6])
{
cc=cc+1;
}
//4
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]>Close[i+7])
{
dd=dd+1;
}
//5
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]>Close[i+8])
{
ee=ee+1;
}
//6
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]<Close[i+8]&&Close[i+8]>Close[i+9])
{
ff=ff+1;
}
//7
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]<Close[i+8]&&Close[i+8]<Close[i+9]&&Close[i+9]>Close[i+10])
{
gg=gg+1;
}
//8
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]<Close[i+8]&&Close[i+8]<Close[i+9]&&Close[i+9]<Close[i+10]&&Close[i+10]>Close[i+11])
{
hh=hh+1;
}
//9
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]<Close[i+8]&&Close[i+8]<Close[i+9]&&Close[i+9]<Close[i+10]&&Close[i+10]<Close[i+11]&&Close[i+11]>Close[i+12])
{
jj=jj+1;
}
//10
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]<Close[i+8]&&Close[i+8]<Close[i+9]&&Close[i+9]<Close[i+10]&&Close[i+10]<Close[i+11]&&Close[i+11]<Close[i+12]&&Close[i+12]>Close[i+13])
{
kk=kk+1;
}
//11
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]<Close[i+8]&&Close[i+8]<Close[i+9]&&Close[i+9]<Close[i+10]&&Close[i+10]<Close[i+11]&&Close[i+11]<Close[i+12]&&Close[i+12]<Close[i+13]&&Close[i+13]>Close[i+14])
{
ll=ll+1;
}
//12
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]<Close[i+8]&&Close[i+8]<Close[i+9]&&Close[i+9]<Close[i+10]&&Close[i+10]<Close[i+11]&&Close[i+11]<Close[i+12]&&Close[i+12]<Close[i+13]&&Close[i+13]<Close[i+14]&&Close[i+14]>Close[i+15])
{
mm=mm+1;
}
//13
if(Close[i+1]>Close[i+2]&&Close[i+2]<Close[i+3]&&Close[i+3]<Close[i+4]&&Close[i+4]<Close[i+5]&&Close[i+5]<Close[i+6]&&Close[i+6]<Close[i+7]&&Close[i+7]<Close[i+8]&&Close[i+8]<Close[i+9]&&Close[i+9]<Close[i+10]&&Close[i+10]<Close[i+11]&&Close[i+11]<Close[i+12]&&Close[i+12]<Close[i+13]&&Close[i+13]<Close[i+14]&&Close[i+14]<Close[i+15]&&Close[i+15]>Close[i+16])
{
nn=nn+1;
}
//=
if(Close[i+1]==Close[i+2])
{
oo=oo+1;
}
//OUTPUT > <
//Frequency NUMBER of consecutive closes greater than and less than the previous.
if(FrequencyNumber) Comment("FrequencyNumber\n# Close[1]>Close[2]\n\n1: "+a+"\n2: "+b+"\n3: "+c+"\n4: "+d+"\n5: "+e+"\n6: "+f+"\n7: "+g+"\n8: "+h+"\n9: "+j+"\n10: "+k
+"\n\n# Close[1]<Close[2]\n\n1: "+aa+"\n2: "+bb+"\n3: "+cc+"\n4: "+dd+"\n5: "+ee+"\n6: "+ff+"\n7: "+gg+"\n8: "+hh+"\n9: "+jj+"\n10: "+kk+"\n11: "+ll+"\n12: "+mm+"\n13: "+nn+"\n==: "+oo+"\n\n Total bars: "+Bars);
}
Everything seems fine. But EA usually opens multiple trades in the same second... The way I built it is very linear and i can't seem to spot the logical mistake. It is basically a random martingale EA to test stuff out. Any indicator (that's why I called it random, haven't decided myself) can be put in there.
Basic idea is that it has an upper and lower threshold which determines when it is in buy zone and when at sell zone. Once it is in either zone, if trend goes against it (determined by indicator's value, not symbol's price) it opens another trade with the same SL/TP of the initial order. Also it checks whether initial trade still runs so it does not open other ones and once the initial trade is open. After that the criterias about the rest of the trades (that go against the trade are different).
The problem is that it opens multiple trades at times that it shouldn't, or like 3-4 trades within the same second or two. Any idea why this happens?
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
input int stepValue = 5;
input double lotsize = 0.01;
input int stoploss = 2000;
input int takeprofit = 140;
input int slippage = 10;
input double upper_border = 60.0;
input double lower_border = 40.0;
const string EAComment = "Xind";
string mode = "";
bool first_trade = false;
int InitTicket = 1;
double X = 0.0;
double X_Last = 0.0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
first_trade = false;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
SearchSignal();
if (mode == "Buy")
{
if (first_trade == false)
{
Buy();
}
if (first_trade == true)
{
MartinCheck();
CloseCheck();
}
}
if (mode == "Sell")
{
if (first_trade == false)
{
Sell();
}
if (first_trade == true)
{
MartinCheck();
CloseCheck();
}
}
}
//+------------------------------------------------------------------+
void Buy()
{
X_Last = X;
first_trade = true;
InitTicket = OrderSend(NULL,OP_BUY,lotsize,Ask,slippage,Ask-stoploss*Point,Ask+takeprofit*Point,EAComment,1,0,clrDarkBlue);
}
//---
void Sell()
{
X_Last = X;
first_trade = true;
InitTicket = OrderSend(NULL,OP_SELL,lotsize,Bid,slippage,Bid+stoploss*Point,Bid-takeprofit*Point,EAComment,1,0,clrDarkRed);
}
//---
void MartinBuy()
{
if (OrderSelect(InitTicket, SELECT_BY_TICKET) == true)
{
double new_SL = OrderStopLoss();
double new_TP = OrderTakeProfit();
int dont_care = OrderSend(NULL,OP_BUY,lotsize,Ask,slippage,new_SL,new_TP,EAComment+" martin",1,0,clrDarkBlue);
}
}
//---
void MartinSell()
{
if (OrderSelect(InitTicket, SELECT_BY_TICKET) == true)
{
double new_SL = OrderStopLoss();
double new_TP = OrderTakeProfit();
int dont_care = OrderSend(NULL,OP_SELL,lotsize,Bid,slippage,new_SL,new_TP,EAComment+" martin",1,0,clrDarkRed);
}
}
//---
void SearchSignal()
{
X = 0.0; //where 0.0, put here the iCustom for external indicators, or some built-in indicator
if (X >= upper_border)
{
mode = "Sell";
}
else if (X <= lower_border)
{
mode = "Buy";
}
else
{
mode = "";
first_trade = false;
InitTicket = 1;
X_Last = 0.0;
}
}
//---
void CloseCheck()
{
if (OrderSelect(InitTicket, SELECT_BY_TICKET))
{
if (OrderCloseTime() == 0)
{
first_trade = true;
}
else if (OrderCloseTime() != 0)
{
first_trade = false;
}
else
{
return;
}
}
}
//---
void MartinCheck()
{
if (mode == "Buy")
{
if ((X_Last - stepValue) >= X)
{
X_Last = X;
MartinBuy();
}
}
if (mode == "Sell")
{
if ((X_Last + stepValue) <= X)
{
X_Last = X;
MartinSell();
}
}
}
The layout of your code makes it possible for several processes to happen in sequence all on the same tick which I assume you do not want. Try changing your code initially to this and work from there:
void OnTick()
{
SearchSignal();
if(mode=="Buy")
{
if(!first_trade) Buy();
else
{
MartinCheck();
CloseCheck();
}
}
else if(mode=="Sell")
{
if(!first_trade) Sell();
else
{
MartinCheck();
CloseCheck();
}
}
}
Remember to use if(...) else to stop executing all functions when it should only be an either/or situation.
My Martingale EA should be stopped automatically if the previously manually set limit has been reached or exceeded. The last trade should expire normally and not be interrupted.
So far, I've tried the following code, without interruption, etc. the code works fine.
I also heard about RemoveExpert, but I do not know how to do it. Am grateful for any help :)
enum tradeD{Buy=1, Sell=2};
input tradeD TradeType = Buy;
input double Initial_Lot = 0.01;
input double Lot_Factor = 2;
input int Max_Spread = 30;
input double Pct_SL = 0.1; // Percentage Stop Loss
input double Pct_TP = 0.1; // Percentage Take Profit
input int Magic_Number= 73726;
input int interrupt = 1,0000;
input bool StopEA = false;
int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
int start()
{
if (StopEA == true) { return(0); } //This line will skip the execution of EA.
}
void OnTick()
{
if(OpenOrders()==0 && (SymbolInfoInteger(Symbol(),SYMBOL_SPREAD)<Max_Spread||Max_Spread==0)){
if(TradeType==Buy){
double flot=Initial_Lot;
double etp=Ask+(Ask*(Pct_TP/100));
etp=NormalizeDouble(etp,Digits);
double esl=Ask-(Ask*(Pct_TP/100));
esl=NormalizeDouble(esl,Digits);
if (ask <= interrupt) { StopEA = true; return(0); }
if(lastProfit()<0){
flot=NormalizeDouble(lastLot()*Lot_Factor,2);
}
int snd=OrderSend(Symbol(),OP_BUY,flot,Ask,10,esl,etp,NULL,Magic_Number,0,clrAliceBlue);
}
if(TradeType==Sell){
double flot=Initial_Lot;
double etp=Bid-(Bid*(Pct_TP/100));
etp=NormalizeDouble(etp,Digits);
double esl=Bid+(Bid*(Pct_TP/100));
esl=NormalizeDouble(esl,Digits);
if (bid >= interrupt) { StopEA = true; return(0); }
if(lastProfit()<0){
flot=NormalizeDouble(lastLot()*Lot_Factor,2);
}
int snd=OrderSend(Symbol(),OP_SELL,flot,Bid,10,esl,etp,NULL,Magic_Number,0,clrAliceBlue);
}
}
//checkProfit();
}
int checkProfit(){
int total=0;
for(int i=OrdersTotal()+5; i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){
string ordsymB = OrderSymbol();
int ordtypeB =OrderType();
int magicnB = OrderMagicNumber();
int magicn=magicnB;
double ordProfit=OrderProfit();
int tick=OrderTicket();
double oLots=OrderLots();
if(ordsymB==Symbol() && magicnB==Magic_Number){
double pctBalT=AccountBalance()*(Pct_TP/100);
double pctBalS=AccountBalance()*(Pct_SL/100);
if(ordProfit>=pctBalT){
int clo=OrderClose(tick,oLots,Close[0],10,clrAntiqueWhite);
}
if(ordProfit<0 && MathAbs(ordProfit)>=pctBalS){
int clo=OrderClose(tick,oLots,Close[0],10,clrAntiqueWhite);
}
}
}
}
return (total);
}
int OpenOrders(){
int total=0;
for(int i=OrdersTotal()+5; i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){
string ordsymB = OrderSymbol();
int ordtypeB =OrderType();
int magicnB = OrderMagicNumber();
int magicn=magicnB;
if(ordsymB==Symbol() && magicnB==Magic_Number){
total++;
}
}
}
return (total);
}
double lastProfit(){
double total=0;
datetime lastTime=0;
for(int i=OrdersHistoryTotal(); i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)){
string ordSym=OrderSymbol();
int ordType=OrderType();
datetime ordTime=OrderOpenTime();
double ordLot=OrderLots();
double ordOp=OrderOpenPrice();
int ordMag=OrderMagicNumber();
double ordProfit=OrderProfit();
if(ordSym==Symbol() && ordTime>lastTime && ordMag==Magic_Number){
lastTime=ordTime;
total=ordProfit;
}
}
}
return(total);
}
double lastLot(){
double total=0;
datetime lastTime=0;
for(int i=OrdersHistoryTotal(); i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)){
string ordSym=OrderSymbol();
int ordType=OrderType();
datetime ordTime=OrderOpenTime();
double ordLot=OrderLots();
double ordOp=OrderOpenPrice();
int ordMag=OrderMagicNumber();
if(ordSym==Symbol() && ordTime>lastTime && ordMag==Magic_Number){
lastTime=ordTime;
total=ordLot;
}
}
}
return(total);
}
if(tick_counter>=ticks_to_close)
{
ExpertRemove();
Print(TimeCurrent(),": ",__FUNCTION__," expert advisor will be unloaded");
}
The code below does compile, but it doesn't run as it should.
I'm not sure what am I doing wrong, so would someone be willing to tell me what I did wrong and what I should have done better.
What do I need to change to make it run properly?
#include<stdio.h>
#include<stdlib.h>
typedef struct sub_Node
{
int value;
struct sub_Node *next;
}sub_Node;
typedef struct Node
{
char *name;
struct Node *next;
struct sub_Node *sub_start;
}Node;
Node *start;
void add_player(char *name)
{
Node *temp;
temp = (Node *)malloc(sizeof(Node));
temp->next = start;
temp->name = name;
temp->sub_start = (sub_Node *)malloc(sizeof(sub_Node));
temp->sub_start->next = NULL;
temp->sub_start->value = -1;
start = temp;
}
void initialize()
{
char *p;
p = "\0";
add_player(p);
}
void remove_player(char *name)
{
Node *p;
for(p = start; p!= NULL; p = p->next)
if(p->name == name)
{
p->name = p->next->name;
p->next = p->next->next;
}
}
sub_Node* add_descending(sub_Node* sub_start, int piece_value)
{
sub_Node *temp, *prev, *next;
temp = (sub_Node *)malloc(sizeof(sub_Node));
temp->value = piece_value;
temp->next = NULL;
prev = NULL;
next = sub_start;
while(next && next->value >= piece_value)
{
prev = next;
next = next->next;
}
if(!next)
{
prev->next = temp;
}
else
{
if(prev)
{
temp->next = prev->next;
prev->next = temp;
}
else
{
temp->next = sub_start;
sub_start = temp;
}
}
return sub_start;
}
void add_piece(char *name, int piece_value)
{
Node *p;
int c;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
p->sub_start = add_descending(p->sub_start, piece_value);
}
void print_pieces(char *name)
{
Node *p;
sub_Node *q;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
{
printf("The values of the owned pieces are:");
for(q = p->sub_start; q->value != -1; q = q->next)
printf(" %d", q->value);
}
}
int lose_piece(char *name)
{
Node *p;
sub_Node *q;
int aux;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
{
for(q = p->sub_start; q->next->value != -1; q = q->next) {}
aux = q->value;
q->value = q->next->value;
q->next = q->next->next;
return aux;
}
}
void print_players()
{
Node *p;
printf("The players are: ");
for(p = start; p->name != "\0"; p = p->next)
printf("%s ", p->name);
printf("\n");
}
int main()
{
initialize();
int y, value;
char name[20];
printf("Insert a digit to execute the desired task:\n"
"<0> end the program\n"
"<1> add a player, who doesn't own any piece yet\n"
"<2> remove a player and all his pieces\n"
"<3> print the name of all the players\n"
"<4> a player gets a piece\n"
"<5> a player loses the piece with the lowest value out of the ones that he has\n"
"<6> prints the pieces of a player in a descending order by value\n\n");
do
{
printf("digit: ");
scanf("%d", &y);
switch(y)
{
case 1:
printf("Insert the player's name: ");
scanf("%s", name);
add_player(name);
break;
case 2:
printf("Insert the player's name: ");
scanf("%s", name);
remove_player(name);
break;
case 3:
print_players();
break;
case 4:
printf("Insert the player's name: ");
scanf("%s", name);
printf("Insert the value of the piece: ");
scanf("%d", value);
add_piece(name, value);
break;
case 5:
printf("Insert the player's name: ");
scanf("%s", name);
printf("\nThe player loses the piece: %d\n", lose_piece(name));
break;
case 6:
printf("Insert the player's name: ");
scanf("%s", name);
print_pieces(name);
}
} while(y != 0);
return 0;
}
your two main problems where this scanf("%d", value); value should be passed by reference like this scanf("%d", &value); and the second is string comparison in c as in your code p->name != "\0" and if(p->name == name) this is wrong because actually you are making comparison between addresses of strings (where it resides in memory) not strings values. to compare strings in c you have to use strcmp and families.
Actually 3 main problems. for setting string values as you did in temp->name = name; is little bit more complicated than that. because you are assigning to temp->name a string from the stack that is volatile (the stack will be more likely invalid soon you return from the function) . in your case you have to alloc a new string by using malloc (and friends) or just by using strdup.
here is as a bonus a slightly rewrite of your program, you will find many advises and is a good starting point for how to structure your code for an easy maintenance.
still want to advise you to change members and variables to more declarative names as in sub_start and sub_Node can be PieceNode and pieces respectively.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct sub_Node
{
int value;
struct sub_Node *next;
}sub_Node;
typedef struct Node
{
char *name;
struct Node *next;
struct Node *prev; // this to make life easyer
struct sub_Node *sub_start;
}Node;
Node *start = NULL;
Node *find_player(char *name){
Node *tmp = start;
while( tmp ){
if(strcmp(tmp->name,name) == 0 )
break;
tmp = tmp->next;
}
return tmp;
}
// int to return Error Code
//
int add_player(char *name)
{
Node *temp;
if( find_player(name)) {
printf("player %s already exists\n", name);
return 1;
}
// do not cast malloc
temp = malloc(sizeof(Node));
if( !temp ){
printf ("not enough memory\n");
return 2;
}
temp->name = strdup ( name); // here was your error
temp->sub_start = NULL; // keep it simple
temp->prev = NULL;
temp->next = start;
if(start)
start->prev = temp;
start = temp;
return 0; // no error
}
void DestroyPieces(sub_Node* piece){
if( piece ) {
DestroyPieces( piece->next );
free( piece );
}
}
// as usual use int to return error code
int remove_player(char *name)
{
Node *player = find_player(name);
if ( !player ){
return 1; // player not found
}
if ( player->next ){
player->next->prev = player->prev;
}
if ( player->prev ){
player->prev->next = player->next;
}
DestroyPieces(player->sub_start);
free(player->name);
free(player);
return 0; // success
}
sub_Node* new_piece(int value){
sub_Node *temp = malloc( sizeof(sub_Node) );
if(temp){
temp->value = value;
temp->next = NULL;
}
return temp;
}
// int to return error code
// pass sub_start as pointer to pointer, as it might be updated
int add_descending(sub_Node** psub_start, int piece_value)
{
sub_Node *piece, *current, *prev = NULL;
if( !psub_start){
return 5; // this should not happen
}
current = *psub_start;
piece = new_piece( piece_value );
if( !piece ) return 1; // no mem
if(!current){
// this is the first and only one
*psub_start = piece;
return 0; // OK
}
while(current && current->value >= piece_value)
{
prev = current;
current = current->next;
}
if( prev )
prev->next = piece;
piece->next = current;
if( current == *psub_start ){
*psub_start = piece;
}
return 0 ; // OK
}
void add_piece(Node * player, int piece_value)
{
if ( !player) {
return ;
}
if(add_descending (&(player->sub_start), piece_value) == 0 )
return ; //OK
printf("an error occured while adding a piece (%d) to player '%s'\n",piece_value,player->name);
}
void print_pieces(Node *player)
{
sub_Node *q;
if( !player ){
return;
}
if( !player->sub_start ){
printf("Player '%s' has no pieces\n",player->name);
return;
}
printf("The values of the owned pieces are:");
for(q = player->sub_start; q != NULL; q = q->next)
printf(" %d", q->value);
printf("\n");
}
void lose_piece(Node *player)
{
if( !player ){
return;
}
sub_Node *q, *prev = NULL;
int aux;
if( !player->sub_start ){
printf("Player '%s' has no pieces\n",player->name);
return;
}
// i think you want drop the last one
for(q = player->sub_start; q->next != NULL ;prev = q, q = q->next) {
;
}
if(prev)
prev->next = NULL;
else
player->sub_start = NULL;
aux = q->value;
free(q);
printf("\nThe player loses the piece: %d\n", aux);
return;
}
void print_players()
{
Node *p;
if( !start ){
printf("there are no players, try to add some\n");
return;
}
printf("The players are: ");
for(p = start; p != NULL; p = p->next)
printf("%s ", p->name);
printf("\n");
}
void print_menu(void){
printf("Insert a digit to execute the desired task:\n"
"<0> end the program\n"
"<1> add a player, who doesn't own any piece yet\n"
"<2> remove a player and all his pieces\n"
"<3> print the name of all the players\n"
"<4> a player gets a piece\n"
"<5> a player loses the piece with the lowest value out of the ones that he has\n"
"<6> prints the pieces of a player in a descending order by value\n\n");
}
Node * get_player(char *name){
Node *player = find_player(name);
if(!player)
printf("Player '%s' do not exists\n",name);
return player;
}
int main()
{
// initialize(); no more needed
int y, value;
char name[20];
Node *player;
print_menu();
do
{
printf("digit: ");
scanf("%d", &y);
switch(y)
{
case 1:
printf("Insert the player's name: ");
scanf("%s", name);
add_player(name);
break;
case 2:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
if( player )
break;
case 3:
print_players();
break;
case 4:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
if( player ){
printf("Insert the value of the piece: ");
scanf("%d", &value);
add_piece(player, value);
}
break;
case 5:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
lose_piece(player);
break;
case 6:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
print_pieces(player);
}
} while(y != 0);
return 0;
}
I have searched for a way to retrieve information from a digital signed PE file. I need the publisher, publisher link , issuer name and subject name. I need winapi / c / c++ code (functions) and i need a fast method , i don't need to check if the signature is valid or not.
Here is code that I wrote for a project of mine that will do this. It returns the details in a struct of type NSIGINFO. Feel free to use it - no attribution necessary, but I would appreciate it if you would leave the copyright intact.
If there's any functions missing (I had to consolidate things from a couple of different places so I may have missed something) please let me know and I'll make the necessary tweaks.
Let me know how this works for you. Good luck.
The header file, NAuthenticode.h:
// NAuthenticode.h: Functions for checking signatures in files
//
// Copyright (c) 2008-2012, Nikolaos D. Bougalis <nikb#bougalis.net>
#ifndef B82FBB5B_C0F8_43A5_9A31_619BB690706C
#define B82FBB5B_C0F8_43A5_9A31_619BB690706C
#include <wintrust.h>
#include <softpub.h>
#include <imagehlp.h>
struct NSIGINFO
{
LONG lValidationResult;
LPTSTR lpszPublisher;
LPTSTR lpszPublisherEmail;
LPTSTR lpszPublisherUrl;
LPTSTR lpszAuthority;
LPTSTR lpszFriendlyName;
LPTSTR lpszProgramName;
LPTSTR lpszPublisherLink;
LPTSTR lpszMoreInfoLink;
LPTSTR lpszSignature;
LPTSTR lpszSerial;
BOOL bHasSigTime;
SYSTEMTIME stSigTime;
};
VOID NCertFreeSigInfo(NSIGINFO *pSigInfo);
BOOL NVerifyFileSignature(LPCTSTR lpszFileName, NSIGINFO *pSigInfo, HANDLE hHandle = INVALID_HANDLE_VALUE);
BOOL NCertGetNameString(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, LPTSTR *lpszNameString);
BOOL NCheckFileCertificates(HANDLE hFile,
VOID (*pCallback)(PCCERT_CONTEXT, LPVOID), PVOID pParam);
#endif
The implementation, NAuthenticode.cpp:
// NAuthenticode.cpp: Various routines related to validating file signatures
//
// Copyright (c) 2008-2012, Nikolaos D. Bougalis <nikb#bougalis.net>
#include "stdafx.h"
#include "NAuthenticode.h"
//////////////////////////////////////////////////////////////////////////
#pragma comment(lib, "crypt32")
#pragma comment(lib, "imagehlp")
#pragma comment(lib, "wintrust")
//////////////////////////////////////////////////////////////////////////
#define SIG_ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
//////////////////////////////////////////////////////////////////////////
// Some utility functions
LPVOID NHeapAlloc(SIZE_T dwBytes)
{
if(dwBytes == 0)
return NULL;
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
}
//////////////////////////////////////////////////////////////////////////
LPVOID NHeapFree(LPVOID lpMem)
{
if(lpMem != NULL)
HeapFree(GetProcessHeap(), 0, lpMem);
return NULL;
}
//////////////////////////////////////////////////////////////////////////
LPSTR NConvertW2A(LPCWSTR lpszString, int nLen, UINT nCodePage)
{
ASSERT(lpszString != NULL);
int ret = WideCharToMultiByte(nCodePage, 0, lpszString, nLen, NULL, 0, NULL, NULL);
if(ret <= 0)
return NULL;
LPSTR lpszOutString = (LPSTR)NHeapAlloc((ret + 1) * sizeof(CHAR));
if(lpszOutString == NULL)
return NULL;
ret = WideCharToMultiByte(nCodePage, 0, lpszString, nLen, lpszOutString, ret, NULL, NULL);
if(ret <= 0)
lpszOutString = (LPSTR)NHeapFree(lpszOutString);
return lpszOutString;
}
//////////////////////////////////////////////////////////////////////////
LPWSTR NDupString(LPCWSTR lpszString, int nLen)
{
if(nLen == -1)
nLen = (int)wcslen(lpszString);
LPWSTR lpszOutString = (LPWSTR)NHeapAlloc((2 + nLen) * sizeof(WCHAR));
if((lpszOutString != NULL) && (nLen != 0))
wcsncpy(lpszOutString, lpszString, nLen + 1);
return lpszOutString;
}
//////////////////////////////////////////////////////////////////////////
LPTSTR NConvertW2T(LPCWSTR lpszString, int nLen, UINT nCodePage)
{
ASSERT(lpszString != NULL);
#ifndef UNICODE
return (LPTSTR)NConvertW2A(lpszString, nLen, nCodePage);
#else
return (LPTSTR)NDupString(lpszString, nLen);
#endif
}
//////////////////////////////////////////////////////////////////////////
LPWSTR NConvertA2W(LPCSTR lpszString, int nLen, UINT nCodePage)
{
ASSERT(lpszString != NULL);
int ret = MultiByteToWideChar(nCodePage, 0, lpszString, nLen, NULL, 0);
if(ret <= 0)
return NULL;
LPWSTR lpszOutString = (LPWSTR)NHeapAlloc((ret + 1) * sizeof(WCHAR));
if(lpszOutString == NULL)
return NULL;
ret = MultiByteToWideChar(nCodePage, 0, lpszString, nLen, lpszOutString, ret);
if(ret <= 0)
lpszOutString = (LPWSTR)NHeapFree(lpszOutString);
return lpszOutString;
}
//////////////////////////////////////////////////////////////////////////
LPWSTR NConvertT2W(LPCTSTR lpszString, int nLen, UINT nCodePage)
{
ASSERT(lpszString != NULL);
#ifndef UNICODE
return NConvertA2W((LPCSTR)lpszString, nLen, nCodePage);
#else
return NDupString((LPWSTR)lpszString, nLen);
#endif
}
//////////////////////////////////////////////////////////////////////////
VOID NCertFreeSigInfo(NSIGINFO *pSigInfo)
{
if(pSigInfo == NULL)
return;
__try
{ // Be extra careful
if(pSigInfo->lpszPublisher)
pSigInfo->lpszPublisher = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher);
if(pSigInfo->lpszPublisherEmail)
pSigInfo->lpszPublisherEmail = (LPTSTR)NHeapFree(pSigInfo->lpszPublisherEmail);
if(pSigInfo->lpszPublisherUrl)
pSigInfo->lpszPublisherUrl = (LPTSTR)NHeapFree(pSigInfo->lpszPublisherUrl);
if(pSigInfo->lpszAuthority)
pSigInfo->lpszAuthority = (LPTSTR)NHeapFree(pSigInfo->lpszAuthority);
if(pSigInfo->lpszProgramName)
pSigInfo->lpszProgramName = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher);
if(pSigInfo->lpszPublisherLink)
pSigInfo->lpszPublisherLink = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher);
if(pSigInfo->lpszMoreInfoLink)
pSigInfo->lpszMoreInfoLink = (LPTSTR)NHeapFree(pSigInfo->lpszMoreInfoLink);
if(pSigInfo->lpszSignature)
pSigInfo->lpszSignature = (LPTSTR)NHeapFree(pSigInfo->lpszSignature);
if(pSigInfo->lpszSerial)
pSigInfo->lpszSerial = (LPTSTR)NHeapFree(pSigInfo->lpszSerial);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
//////////////////////////////////////////////////////////////////////////
static BOOL NCertGetNameString(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, LPTSTR *lpszNameString)
{
if(pCertContext == NULL)
return FALSE;
DWORD dwData = CertGetNameString(pCertContext, dwType, 0, NULL, NULL, 0);
if(dwData == 0)
return FALSE;
*lpszNameString = (LPTSTR)NHeapAlloc((dwData + 1) * sizeof(TCHAR));
if(*lpszNameString == NULL)
return FALSE;
dwData = CertGetNameString(pCertContext, dwType, dwFlags, NULL, *lpszNameString, dwData);
if(dwData == 0)
{
NHeapFree(*lpszNameString);
return FALSE;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
static BOOL NCryptDecodeObject(__in LPCSTR lpszObjectId, __in_bcount(cbEncoded) const BYTE *pbEncoded, __in DWORD cbEncoded,
__inout DWORD &dwBuffer, __out void *pBuffer = NULL, __in DWORD dwFlags = 0)
{
if(((pBuffer == NULL) && (dwBuffer != 0)) || ((dwBuffer == 0) && (pBuffer != NULL)))
{ // What? You're passing a NULL pointer an a non-zero size? You so crazy!!!!
ASSERT(FALSE);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return CryptDecodeObject(SIG_ENCODING, lpszObjectId, pbEncoded, cbEncoded, dwFlags, pBuffer, &dwBuffer);
}
//////////////////////////////////////////////////////////////////////////
static BOOL NCryptDecodeObject(__in LPCSTR lpszObjectId, __in PCRYPT_ATTR_BLOB pObject,
__inout DWORD &dwBuffer, __out void *pBuffer = NULL, __in DWORD dwFlags = 0)
{
if((pObject == NULL) || ((dwBuffer == 0) && (pBuffer != NULL)) || ((dwBuffer != 0) && (pBuffer == NULL)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return CryptDecodeObject(SIG_ENCODING, lpszObjectId, pObject->pbData, pObject->cbData, dwFlags, pBuffer, &dwBuffer);
}
//////////////////////////////////////////////////////////////////////////
static BOOL WGetSignTimestamp(PCRYPT_ATTRIBUTES pAttributes, SYSTEMTIME &stTime, LPCSTR lpszObjId)
{
if((pAttributes == NULL) || (pAttributes->cAttr == 0) || (lpszObjId == NULL) || (*lpszObjId == 0))
return FALSE;
for(DWORD dwAttr = 0; dwAttr < pAttributes->cAttr; dwAttr++)
{
if(strcmp(lpszObjId, pAttributes->rgAttr[dwAttr].pszObjId) == 0)
{
DWORD dwSize = sizeof(FILETIME);
FILETIME ftCert;
if(NCryptDecodeObject(lpszObjId, &pAttributes->rgAttr[dwAttr].rgValue[0], dwSize, (PVOID)&ftCert))
{
FILETIME ftLocal;
if(FileTimeToLocalFileTime(&ftCert, &ftLocal) && FileTimeToSystemTime(&ftLocal, &stTime))
return TRUE;
}
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
static BOOL NVerifyFileSignatureWorker(LPWSTR lpszFileName, WINTRUST_DATA &wtData, NSIGINFO *pSigInfo)
{
if(pSigInfo != NULL)
memset(pSigInfo, 0, sizeof(NSIGINFO));
GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
BOOL bVerified = FALSE;
LONG lRet = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &wtData);
if(lRet != 0)
{
if(pSigInfo != NULL)
pSigInfo->lValidationResult = lRet;
return FALSE;
}
if(pSigInfo == NULL)
return TRUE;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
if(!CryptQueryObject(CERT_QUERY_OBJECT_FILE, lpszFileName, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, &hStore, &hMsg, NULL))
return FALSE;
PCMSG_SIGNER_INFO pSignerInfo = NULL, pCounterSignerInfo = NULL;
DWORD dwSignerInfo = 0, dwCounterSignerInfo = 0;
if(CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo) && (dwSignerInfo != 0))
pSignerInfo = (PCMSG_SIGNER_INFO)NHeapAlloc(dwSignerInfo);
if((pSignerInfo != NULL) && CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)pSignerInfo, &dwSignerInfo))
{
for(DWORD dwAttr = 0; dwAttr < pSignerInfo->AuthAttrs.cAttr; dwAttr++)
{
if((strcmp(SPC_SP_OPUS_INFO_OBJID, pSignerInfo->AuthAttrs.rgAttr[dwAttr].pszObjId) != 0))
continue;
PSPC_SP_OPUS_INFO pOpus = NULL;
DWORD dwData = 0;
if(NCryptDecodeObject(SPC_SP_OPUS_INFO_OBJID, &pSignerInfo->AuthAttrs.rgAttr[dwAttr].rgValue[0], dwData) && (dwData != 0))
pOpus = (PSPC_SP_OPUS_INFO)NHeapAlloc(dwData);
if((pOpus != NULL) && NCryptDecodeObject(SPC_SP_OPUS_INFO_OBJID, &pSignerInfo->AuthAttrs.rgAttr[dwAttr].rgValue[0], dwData, (PVOID)pOpus))
{
pSigInfo->lpszProgramName = NConvertW2T(pOpus->pwszProgramName);
if(pOpus->pPublisherInfo != NULL)
{
switch(pOpus->pPublisherInfo->dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
pSigInfo->lpszPublisherLink = NConvertW2T(pOpus->pPublisherInfo->pwszUrl);
break;
case SPC_FILE_LINK_CHOICE:
pSigInfo->lpszPublisherLink = NConvertW2T(pOpus->pPublisherInfo->pwszFile);
break;
}
}
if(pOpus->pMoreInfo != NULL)
{
switch (pOpus->pMoreInfo->dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
pSigInfo->lpszMoreInfoLink = NConvertW2T(pOpus->pMoreInfo->pwszUrl);
break;
case SPC_FILE_LINK_CHOICE:
pSigInfo->lpszMoreInfoLink = NConvertW2T(pOpus->pMoreInfo->pwszFile);
break;
}
}
}
if(pOpus != NULL)
NHeapFree(pOpus);
break;
}
CERT_INFO ci;
ci.Issuer = pSignerInfo->Issuer;
ci.SerialNumber = pSignerInfo->SerialNumber;
PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore, SIG_ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&ci, NULL);
if(pCertContext != NULL)
{
if(pCertContext->pCertInfo->SerialNumber.cbData != 0)
{
pSigInfo->lpszSerial = (LPTSTR)NHeapAlloc(((pCertContext->pCertInfo->SerialNumber.cbData * 2) + 1) * sizeof(TCHAR));
if(pSigInfo->lpszSerial != NULL)
{
LPTSTR lpszPointer = pSigInfo->lpszSerial;
for(DWORD dwCount = pCertContext->pCertInfo->SerialNumber.cbData; dwCount != 0; dwCount--)
lpszPointer += _stprintf(lpszPointer, _T("%02X"), pCertContext->pCertInfo->SerialNumber.pbData[dwCount - 1]);
}
}
if(!NCertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, &pSigInfo->lpszFriendlyName))
pSigInfo->lpszFriendlyName = NULL;
if(!NCertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, &pSigInfo->lpszAuthority))
pSigInfo->lpszAuthority = NULL;
if(!NCertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, &pSigInfo->lpszPublisher))
pSigInfo->lpszPublisher = NULL;
if(!NCertGetNameString(pCertContext, CERT_NAME_URL_TYPE, 0, &pSigInfo->lpszPublisherUrl))
pSigInfo->lpszPublisherUrl = NULL;
if(!NCertGetNameString(pCertContext, CERT_NAME_EMAIL_TYPE, 0, &pSigInfo->lpszPublisherEmail))
pSigInfo->lpszPublisherEmail = NULL;
CertFreeCertificateContext(pCertContext);
}
for(DWORD dwAttr = 0, dwData; dwAttr < pSignerInfo->AuthAttrs.cAttr; dwAttr++)
{
if((strcmp(szOID_RSA_signingTime, pSignerInfo->AuthAttrs.rgAttr[dwAttr].pszObjId) == 0) && (pSignerInfo->AuthAttrs.rgAttr[dwAttr].cValue != 0))
{
FILETIME ftCert;
dwData = sizeof(FILETIME);
if(NCryptDecodeObject(szOID_RSA_signingTime, &pSignerInfo->AuthAttrs.rgAttr[dwAttr].rgValue[0], dwData, (PVOID)&ftCert))
{
FILETIME ftLocal;
if(!FileTimeToLocalFileTime(&ftCert, &ftLocal))
{
if(!FileTimeToSystemTime(&ftLocal, &pSigInfo->stSigTime))
memset(&pSigInfo->stSigTime, 0, sizeof(SYSTEMTIME));
}
}
}
}
for(DWORD dwAttr = 0; dwAttr < pSignerInfo->UnauthAttrs.cAttr; dwAttr++)
{
if(strcmp(pSignerInfo->UnauthAttrs.rgAttr[dwAttr].pszObjId, szOID_RSA_counterSign) == 0)
{
if(NCryptDecodeObject(PKCS7_SIGNER_INFO, &pSignerInfo->UnauthAttrs.rgAttr[dwAttr].rgValue[0], dwCounterSignerInfo) && (dwCounterSignerInfo != 0))
pCounterSignerInfo = (PCMSG_SIGNER_INFO)NHeapAlloc(dwCounterSignerInfo);
if((pCounterSignerInfo != NULL) && !NCryptDecodeObject(PKCS7_SIGNER_INFO, &pSignerInfo->UnauthAttrs.rgAttr[dwAttr].rgValue[0], dwCounterSignerInfo, pCounterSignerInfo))
pCounterSignerInfo = (PCMSG_SIGNER_INFO)NHeapFree(pCounterSignerInfo);
break;
}
}
if(pCounterSignerInfo != NULL)
{
pSigInfo->bHasSigTime = WGetSignTimestamp(&pCounterSignerInfo->AuthAttrs, pSigInfo->stSigTime, szOID_RSA_signingTime);
if(!pSigInfo->bHasSigTime)
memset(&pSigInfo->stSigTime, 0, sizeof(SYSTEMTIME));
}
}
if(pSignerInfo != NULL)
NHeapFree(pSignerInfo);
if(pCounterSignerInfo != NULL)
NHeapFree(pCounterSignerInfo);
if(hStore != NULL)
CertCloseStore(hStore, 0);
if(hMsg != NULL)
CryptMsgClose(hMsg);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
BOOL NVerifyFileSignature(LPCTSTR lpszFileName, NSIGINFO *pSigInfo, HANDLE hHandle)
{
if(pSigInfo != NULL)
memset(pSigInfo, 0, sizeof(NSIGINFO));
if(lpszFileName == NULL)
return FALSE;
if((lpszFileName[0] != 0) && (_tcsnicmp(lpszFileName, _T("\\??\\"), 4) == 0))
lpszFileName += 4;
if(lpszFileName[0] == 0)
return FALSE;
LPWSTR lpwszFileName = NConvertT2W(lpszFileName);
if(lpwszFileName == NULL)
return FALSE;
BOOL bOK = FALSE;
__try
{ // be very careful...
WINTRUST_FILE_INFO wtFileInfo;
memset(&wtFileInfo, 0, sizeof(WINTRUST_FILE_INFO));
wtFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
wtFileInfo.pcwszFilePath = lpwszFileName;
if(hHandle != INVALID_HANDLE_VALUE)
wtFileInfo.hFile = hHandle;
WINTRUST_DATA wtData;
memset(&wtData, 0, sizeof(WINTRUST_DATA));
wtData.cbStruct = sizeof(WINTRUST_DATA);
wtData.dwUIChoice = WTD_UI_NONE;
wtData.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
wtData.dwUnionChoice = WTD_CHOICE_FILE;
wtData.pFile = &wtFileInfo;
if(NVerifyFileSignatureWorker(lpwszFileName, wtData, pSigInfo))
bOK = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
if(pSigInfo != NULL)
{
if(pSigInfo->lpszPublisher)
pSigInfo->lpszPublisher = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher);
if(pSigInfo->lpszAuthority)
pSigInfo->lpszAuthority = (LPTSTR)NHeapFree(pSigInfo->lpszAuthority);
if(pSigInfo->lpszProgramName)
pSigInfo->lpszProgramName = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher);
if(pSigInfo->lpszPublisherLink)
pSigInfo->lpszPublisherLink = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher);
if(pSigInfo->lpszMoreInfoLink)
pSigInfo->lpszMoreInfoLink = (LPTSTR)NHeapFree(pSigInfo->lpszMoreInfoLink);
if(pSigInfo->lpszSignature)
pSigInfo->lpszSignature = (LPTSTR)NHeapFree(pSigInfo->lpszSignature);
if(pSigInfo->lpszSerial)
pSigInfo->lpszSerial = (LPTSTR)NHeapFree(pSigInfo->lpszSerial);
}
bOK = FALSE;
}
NHeapFree(lpwszFileName);
return bOK;
}
//////////////////////////////////////////////////////////////////////////
BOOL NCheckFileCertificates(HANDLE hFile, VOID (*pCallback)(PCCERT_CONTEXT, LPVOID), PVOID pParam)
{
DWORD dwCerts = 0;
if(!ImageEnumerateCertificates(hFile, CERT_SECTION_TYPE_ANY, &dwCerts, NULL, 0))
return FALSE;
for(DWORD dwCount = 0; dwCount < dwCerts; dwCount++)
{
WIN_CERTIFICATE wcHdr;
memset(&wcHdr, 0, sizeof(WIN_CERTIFICATE));
wcHdr.dwLength = 0;
wcHdr.wRevision = WIN_CERT_REVISION_1_0;
if(!ImageGetCertificateHeader(hFile, dwCount, &wcHdr))
return FALSE;
DWORD dwLen = sizeof(WIN_CERTIFICATE) + wcHdr.dwLength;
WIN_CERTIFICATE *pWinCert = (WIN_CERTIFICATE *)NHeapAlloc(dwLen);
if(pWinCert == NULL)
return FALSE;
if(!ImageGetCertificateData(hFile, dwCount, pWinCert, &dwLen))
{ // problem getting certificate, return failure
NHeapFree(pWinCert);
return FALSE;
}
// extract the PKCS7 signed data
CRYPT_VERIFY_MESSAGE_PARA cvmp;
memset(&cvmp, 0, sizeof(CRYPT_VERIFY_MESSAGE_PARA));
cvmp.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
cvmp.dwMsgAndCertEncodingType = SIG_ENCODING;
PCCERT_CONTEXT pCertContext = NULL;
if(!CryptVerifyMessageSignature(&cvmp, dwCount, pWinCert->bCertificate, pWinCert->dwLength, NULL, NULL, &pCertContext))
{
NHeapFree(pWinCert);
return FALSE;
}
// Now, pass this context on to our callback function (if any)
if(pCallback != NULL)
pCallback(pCertContext, pParam);
if(!CertFreeCertificateContext(pCertContext))
{
NHeapFree(pWinCert);
return FALSE;
}
NHeapFree(pWinCert);
}
return TRUE;
}
Microsoft provides a way to do it in this support link: How To Get Information from Authenticode Signed Executables
You can use the WinVerifyTrust() API to verify an Authenticode signed
executable.
Although a signature is verified, a program may also have to do the
following:
Determine the details of the certificate that signed the
executable.
Determine the date and time that the file was time
stamped.
Retrieve the URL link associated with the file.
Retrieve the timestamp certificate.
This article demonstrates how to use
CryptQueryObject() API to retrieve detailed information from an
Authenticode signed executable.