Wouldnt it be nice if you were paid to do something you do as part of
your everyday routine ?? Like searching the web
Sounds too good to be true .. doesnt it ..
At first i was skeptical about it , but after seeing the results , thought i will share the information.
You should try it to believe it ...
SlashMySearch pays you to use their search engine...
Use SlashMySearch as your primary search engine and earn ....
The best part is joining is absolutely free...
You do not have to install any software or go through long guides.
All you need to spend is 2 minutes to get started.
There is also a referral program. You get pais for your referrals' activity ...
What are you waiting for
Join Now ... Hurry Up..
Please use the below link. In this way both u and i will be benefitted.
http://www.slashmysearch.com/earn/signup.html?id=57034
In case you have any doubts , feel free to ask questions.
Tuesday, July 31, 2007
Friday, June 29, 2007
How to debug a background job
At times you might find yourself in a situation to debug background jobs.
Is it possible in SAP?? Yes it is ...
There are two ways to achieve the same.
1) Goto sm37 (Job overview ). Select the job you want to debug , enter JDBG in the OKCODE.
This can be used to debug any process.
2) Code an infinite loop in your program at the point where you want to debug.
ex
do
if i=1
exit
endif
enddo.
Start the program.
Goto sm50 ( Process overview ). The process appears in the running state and then goes to hanging state.
click on the process.
Goto Program/mode -> program -> debugging.
Change the value of i at runtime in the debugger.
Is it possible in SAP?? Yes it is ...
There are two ways to achieve the same.
1) Goto sm37 (Job overview ). Select the job you want to debug , enter JDBG in the OKCODE.
This can be used to debug any process.
2) Code an infinite loop in your program at the point where you want to debug.
ex
do
if i=1
exit
endif
enddo.
Start the program.
Goto sm50 ( Process overview ). The process appears in the running state and then goes to hanging state.
click on the process.
Goto Program/mode -> program -> debugging.
Change the value of i at runtime in the debugger.
How to run sap sessions
After all the hustle bustle , u created a session ... Good Job ...
To process it you need to go to transaction sm35 , and then start the session.
Isnt this too much of work in real time ...
There is an easier way to handle sessions.
The program RSBDCSUB executes sessions that have not yet been processed.
This program can be scheduled periodically in the Background Jobs ( sm36).
There we go ..
To process it you need to go to transaction sm35 , and then start the session.
Isnt this too much of work in real time ...
There is an easier way to handle sessions.
The program RSBDCSUB executes sessions that have not yet been processed.
This program can be scheduled periodically in the Background Jobs ( sm36).
There we go ..
Restarting Interrupted Sessions in SAP
sm35 is the transaction code for batch input sessions.
A session that was interrupted while it was running will be in the Active state.
To retsart the session it must first be released.
Click on the session and select relese from the toolbar.
You can then start the session.
All transactions that were completed sucessfully during the previous run will be
skipped.
The transaction that was getting executed while the problem ocurred will be
repeated.
If the generation of the session itself was interrupted , it will be in
Being generated state.
You can run such a session.
But there is no gurantee that it has all the transaction information.
So in this case it is best to recreate the session.
A session that was interrupted while it was running will be in the Active state.
To retsart the session it must first be released.
Click on the session and select relese from the toolbar.
You can then start the session.
All transactions that were completed sucessfully during the previous run will be
skipped.
The transaction that was getting executed while the problem ocurred will be
repeated.
If the generation of the session itself was interrupted , it will be in
Being generated state.
You can run such a session.
But there is no gurantee that it has all the transaction information.
So in this case it is best to recreate the session.
Wednesday, June 27, 2007
Understanding BDC call transaction
Lets derive the BDC process...
The aim of BDC is to transfer data from flat file ( or xls ) to the appropriate database tables in SAP.
To transfer data into the DB tables , an internal table should be used in the program.
Here we go to our first step
1) Declare an internal table with relevant fields.
How do u transfer data into your internal table from the flat file.
We have a function module gui_upload for this purpose.
This is our next step
2) Upload data from flat file into the internal table.
Now we have data in our internal table , we need to transfer it to the DB tables.
SQL is an option but is not advisable because a single transaction affects more than one table.
Hence SQL is not a safe way of transferring data.
So whats the other way to accomplish the same.
We are all aware that transaction codes exist for the creation of data.
Ex xk01 is the code for creating a vendor master data.
Transactions can be called from the program using CALL TRANSACTION 'TCODE'.
Now, the above statement causes opens a new transaction and one has to manually
enter data. This defeats the whole purpose of BDC. There should be a way to automate the process of enterring data.
Well, there is a way to automate the process.
CALL TRANSACTION USING
MODE UPDATE MESSAGES INTO
is used for the same.
Dont panic .. you will understand the syntax once u understand the logic.
Since we want to automate the data entry process in the transaction, there should be some
means by which the transaction receives data t be entered.
BDCDATA holds the data and actions to be performed to complete the transaction.
For example , to comple a transaction , one might have to go through a sequence of screens , entering values in the fields.
This sequence and data is stored in BDCDATA structure.
To explain in very simple terms , BDCDATA tells the system what it should do in that transaction.
For ex. the contents of a typical BDCDATA structure for xd01 translates to
"Fill value for customer,sales organization, distribution channel ,
then move on to screen 1020.
In screen 1020 fill values for name , search term ...
Then move on to screen 1030"
Phew...
Ok now u r happy that this BDCDATA does some magic and gets the system to fill values in the transaction.
Remember in programming there is no magic , what u ask the sytem to do is what u get ...
Someone has to fill the BDCDATA structure.
In my previous blog i have explained BDCDATA in detail.
Filling the structure manually is a big pain ...
There is an easier method to do it ...
IN SAP there is a concept called "Record transaction" ..
Goto shdb , start new recording , enter the transaction code that u want to record ,
keep filling values , save the recording...
All actions that u performed throughout the entire transaction is stored.
Now goto edit , create program. This creates a program with information about the recording.
Copy the list of performs used to fill the bdc data.
This list populates the structure BDCDATA.
You dont have the headache of populating it urself ..
I guess the remaining steps will fall into place now..
3) Process itab
4) For each entry of itab create a bdcdata structure with field values from the itab.
5) CALL TRANSACTION USING
MODE UPDATE MESSAGES INTO
6) check sy-subrc and process errors.
The aim of BDC is to transfer data from flat file ( or xls ) to the appropriate database tables in SAP.
To transfer data into the DB tables , an internal table should be used in the program.
Here we go to our first step
1) Declare an internal table with relevant fields.
How do u transfer data into your internal table from the flat file.
We have a function module gui_upload for this purpose.
This is our next step
2) Upload data from flat file into the internal table.
Now we have data in our internal table , we need to transfer it to the DB tables.
SQL is an option but is not advisable because a single transaction affects more than one table.
Hence SQL is not a safe way of transferring data.
So whats the other way to accomplish the same.
We are all aware that transaction codes exist for the creation of data.
Ex xk01 is the code for creating a vendor master data.
Transactions can be called from the program using CALL TRANSACTION 'TCODE'.
Now, the above statement causes opens a new transaction and one has to manually
enter data. This defeats the whole purpose of BDC. There should be a way to automate the process of enterring data.
Well, there is a way to automate the process.
CALL TRANSACTION USING
MODE UPDATE MESSAGES INTO
is used for the same.
Dont panic .. you will understand the syntax once u understand the logic.
Since we want to automate the data entry process in the transaction, there should be some
means by which the transaction receives data t be entered.
BDCDATA holds the data and actions to be performed to complete the transaction.
For example , to comple a transaction , one might have to go through a sequence of screens , entering values in the fields.
This sequence and data is stored in BDCDATA structure.
To explain in very simple terms , BDCDATA tells the system what it should do in that transaction.
For ex. the contents of a typical BDCDATA structure for xd01 translates to
"Fill value for customer,sales organization, distribution channel ,
then move on to screen 1020.
In screen 1020 fill values for name , search term ...
Then move on to screen 1030"
Phew...
Ok now u r happy that this BDCDATA does some magic and gets the system to fill values in the transaction.
Remember in programming there is no magic , what u ask the sytem to do is what u get ...
Someone has to fill the BDCDATA structure.
In my previous blog i have explained BDCDATA in detail.
Filling the structure manually is a big pain ...
There is an easier method to do it ...
IN SAP there is a concept called "Record transaction" ..
Goto shdb , start new recording , enter the transaction code that u want to record ,
keep filling values , save the recording...
All actions that u performed throughout the entire transaction is stored.
Now goto edit , create program. This creates a program with information about the recording.
Copy the list of performs used to fill the bdc data.
This list populates the structure BDCDATA.
You dont have the headache of populating it urself ..
I guess the remaining steps will fall into place now..
3) Process itab
4) For each entry of itab create a bdcdata structure with field values from the itab.
5) CALL TRANSACTION USING
MODE UPDATE MESSAGES INTO
6) check sy-subrc and process errors.
Tuesday, June 26, 2007
UPLOAD data from Excel to Itab
The function module
ALSM_EXCEL_TO_INTERNAL_TABLE is used to migrate data from an excel file
into an internal table.
The internal table should be declared of type ALSMEX_TABLINE.
This structure has the following fields
ROW COL VALUE.
Each cell of the excel data is stored as a record in the table.
ALSM_EXCEL_TO_INTERNAL_TABLE is used to migrate data from an excel file
into an internal table.
The internal table should be declared of type ALSMEX_TABLINE.
This structure has the following fields
ROW COL VALUE.
Each cell of the excel data is stored as a record in the table.
BDCDATA structure in depth
BDCDATA structure stores the data that needs to be transferred to the SAP system.
The structure has the following fields.
PROGRAM
Name of the program.
DYNPRO
Screen Number
DYNBEGIN
Marks the beginning of a screen in a transaction
FNAM
Field NAme
FVAL
Field value.
The records can be divided into screen records and field records.
Each screen of the transaction is assigned a row in the BDCDATA structure.
This row contains Program,Dynpro and Dynbegin fields.
Dynbegin is set to 'X' to mark the beginning of the screen.
A record is assigned for each of the values entered.
These field records have only FNAM and FVAL.
The function codes of commands entered during the transaction are
entered in the structure too.
The structure has the following fields.
PROGRAM
Name of the program.
DYNPRO
Screen Number
DYNBEGIN
Marks the beginning of a screen in a transaction
FNAM
Field NAme
FVAL
Field value.
The records can be divided into screen records and field records.
Each screen of the transaction is assigned a row in the BDCDATA structure.
This row contains Program,Dynpro and Dynbegin fields.
Dynbegin is set to 'X' to mark the beginning of the screen.
A record is assigned for each of the values entered.
These field records have only FNAM and FVAL.
The function codes of commands entered during the transaction are
entered in the structure too.
Monday, June 25, 2007
HIDE Technique
ex.
loop at itab
write ...
hide itab.
endloop.
HIDE keyword creates a table of the form
linenumber fields.
When at line selection event is triggered, the linne number is referred in the HIDE table,
The corresponding fields are copied onto the itab header.
This can be used later in the program.
loop at itab
write ...
hide itab.
endloop.
HIDE keyword creates a table of the form
linenumber fields.
When at line selection event is triggered, the linne number is referred in the HIDE table,
The corresponding fields are copied onto the itab header.
This can be used later in the program.
Thursday, June 21, 2007
Dialog Processor and List processor
A screen sequence is handled by dialog processor.
Within a screen, list sequence is handled by list processor.
The dialog processor handles flow logic screen after screen , triggering the appropriate
ABAP modules in the module pool pgm.
One can switch between dialog processor and list processor using
leave to listprocessing , call screen commands.
The o/p of report pgm is called list.
Conceptually , the o/p comprises of a list screen.
The list screen in turn comprises of basic list+details lists.
Each of these lists is assigned a list index starting from 0 for the basic list.
The index of a particular list can be retrieved from sy-lsind system field.
The list processor handles 'at line selection' and 'at user command events'.
At the end of displaying the list , the list processor checks if the sy-lsind value is lesser than the
current list index. If so , the lists in between are deleted , the current list is set to the
number in sy-lsind.
Suppose you want to move from 3rd list to 1st list using back button ,
just decrement the sy-lsind value programatically and then press back button.
Within a screen, list sequence is handled by list processor.
The dialog processor handles flow logic screen after screen , triggering the appropriate
ABAP modules in the module pool pgm.
One can switch between dialog processor and list processor using
leave to listprocessing , call screen commands.
The o/p of report pgm is called list.
Conceptually , the o/p comprises of a list screen.
The list screen in turn comprises of basic list+details lists.
Each of these lists is assigned a list index starting from 0 for the basic list.
The index of a particular list can be retrieved from sy-lsind system field.
The list processor handles 'at line selection' and 'at user command events'.
At the end of displaying the list , the list processor checks if the sy-lsind value is lesser than the
current list index. If so , the lists in between are deleted , the current list is set to the
number in sy-lsind.
Suppose you want to move from 3rd list to 1st list using back button ,
just decrement the sy-lsind value programatically and then press back button.
Popup box function module
POPUP_WITH_TABLE_DISPLAY is the function module to display contents
of an itab in a popup window.
It takes the name of the itab as i/p.
Displays the contents in a popup window.
On the window you can select any line.
The index of the itab corresponding to the line selected is stored in 'choice'.
In your program declare a variable say , indx like sy-tabix.
Pass this in the import parameter 'choice' during function call.
Later , use the variable in a read statement as follows
to retrieve the contents of the clicked line.
read table itab index indx.
of an itab in a popup window.
It takes the name of the itab as i/p.
Displays the contents in a popup window.
On the window you can select any line.
The index of the itab corresponding to the line selected is stored in 'choice'.
In your program declare a variable say , indx like sy-tabix.
Pass this in the import parameter 'choice' during function call.
Later , use the variable in a read statement as follows
to retrieve the contents of the clicked line.
read table itab index indx.
Thursday, June 14, 2007
Passing itabs to subroutines
The aim of the program is to take select-option from the main program and pass the same to a subroutine.
I was able to achieve the same with FORM <> TABLES <>
In order to pass itabs to your subroutine use tables instead of USING in both the
FORM and PERFORM statement.
My pgm was of the form.
FORM sub1 TABLES itab
.
select * from mara into <> where matnr in itab.
END FORM
declare an itab itab1
PERFORM sub1 TABLES itab1.
In my program i obtained select options in my main program and passed it using PERFORM TABLES.
The documention of FORM specifies that TABLES is obsolete , the same functionality can be obtained with USING. When i tried the same the
select * from mara into <> where matnr in itab.
in my program failed in syntax check.
Quiet obvious as SAP does not understand what type i am passing.
I also tried adding like statement in FORM.
It failed too.
Right now TABLES is the working way i know of to pass itabs to subs.
I was able to achieve the same with FORM <> TABLES <>
In order to pass itabs to your subroutine use tables instead of USING in both the
FORM and PERFORM statement.
My pgm was of the form.
FORM sub1 TABLES itab
.
select * from mara into <> where matnr in itab.
END FORM
declare an itab itab1
PERFORM sub1 TABLES itab1.
In my program i obtained select options in my main program and passed it using PERFORM TABLES.
The documention of FORM specifies that TABLES is obsolete , the same functionality can be obtained with USING. When i tried the same the
select * from mara into <> where matnr in itab.
in my program failed in syntax check.
Quiet obvious as SAP does not understand what type i am passing.
I also tried adding like statement in FORM.
It failed too.
Right now TABLES is the working way i know of to pass itabs to subs.
Modify Screen
What is PBO event.
Process B4 Output.
This event is triggered before sending the slecetion screen elements to the presentation layer.
In lay man terms before displaying the slecetion screen.
AT SELECTION-SCREEN OUTPUT event is triggered during PBO.
What is PAI.
Process After Input.
This event is triggered after giving inputs to the selection screen.
AT SELECTION-SCREEN , AT SELECTION-SCREEN ON events are triggered during PAI.
Modify screen makes sence only at PBO.
Changes made to screen during PAI have no effect.
Process B4 Output.
This event is triggered before sending the slecetion screen elements to the presentation layer.
In lay man terms before displaying the slecetion screen.
AT SELECTION-SCREEN OUTPUT event is triggered during PBO.
What is PAI.
Process After Input.
This event is triggered after giving inputs to the selection screen.
AT SELECTION-SCREEN , AT SELECTION-SCREEN ON events are triggered during PAI.
Modify screen makes sence only at PBO.
Changes made to screen during PAI have no effect.
Itab Events.
I had a problem getting the events to work when i use any fiels other than the first of an itab
as the working fields.
To be clear,
Suppose itab is an internal table with fields f1 , f2 and f3 in this order.
Everything works fine when the records are sorted by f1 , f1 is used in AT statements as
AT new f1.
However if i sort the records by f2 and use AT NEW f2 , the behavior is not as expected.
If someone gets through with this do let me know.
as the working fields.
To be clear,
Suppose itab is an internal table with fields f1 , f2 and f3 in this order.
Everything works fine when the records are sorted by f1 , f1 is used in AT statements as
AT new f1.
However if i sort the records by f2 and use AT NEW f2 , the behavior is not as expected.
If someone gets through with this do let me know.
Tuesday, June 12, 2007
SAP Function Modules
Function modules in SAP are similar to subroutines except that they are global.
They can be accessed by any program.
They can handle exceptions and can return values unlike subroutines.
Every function should be defined in a function group.
You can either use existing groups or create your own function groups.
Lets assume that you create a func grp called FGRP.
SAP creates program called SAPLZ_FGRP .
This program includes a program called LZ_FGRPTOP.
These have to activated before using the function in this group.
Not activating this gives ativation errors.
For example if u create a function Z_FUNCTTEST in group Z_FGRP,
You have to activate Z_FUNCTTEST,LZ_FGRTOP,SAPLZ_FGRP.
To call functions in a program use the pattern option and click the function you want to insert.
They can be accessed by any program.
They can handle exceptions and can return values unlike subroutines.
Every function should be defined in a function group.
You can either use existing groups or create your own function groups.
Lets assume that you create a func grp called FGRP.
SAP creates program called SAPLZ_FGRP .
This program includes a program called LZ_FGRPTOP.
These have to activated before using the function in this group.
Not activating this gives ativation errors.
For example if u create a function Z_FUNCTTEST in group Z_FGRP,
You have to activate Z_FUNCTTEST,LZ_FGRTOP,SAPLZ_FGRP.
To call functions in a program use the pattern option and click the function you want to insert.
Monday, June 11, 2007
SAP ABAP implicit inner join
select from tab1 into table itab for all entries in itab2 where f1 = itab2-f1
The statement gets clear when one understands the concept of inner join.
inner join creates a cross product of all entries from the tables specified.
It then checks the where condition and holds only those records for which the condition is satisfied.
Lets first take an example for cross product using sets.
We'll then move on to tables.
Consider two sets S1 and S2.
S1 = { 1, 2 , 3 }.
S2 = { 4 , 5 }
S1 Cross S2 = { 1, 4 } { 1,5} {2,4} {2,5} {3,4} {3,5}.
We will now apply the same concept to tables.
When it comes to tables , S1 , S2 will be the tables with records {1,2,3} and {4,5} respectively.
Lets take an example.
Tab1. - has two fields f1 and f2
Sory for the poor table representation. This is the best i could muster.
f1 f2
1 a
2 b
Tab2 has two fields f1 and f3
f1 f3
1 Rec1
1 Rec2
2 Rec3
The cross product is
where first two columns belong to tab1 , last two belong to tab2.
f1 f2 tab2-f1 tab2-f3
1 a 1 Rec1
1 a 1 Rec2
1 a 2 Rec3
2 b 1 Rec1
2 b 1 Rec2
2 b 2 Rec3
from the above only rows which satisfy the condition f1=tab2-f1 are selected
so only records 1 , 2 6 are selected.
f1 and tab2-f1 is merged as they are equal.
This is how select with for all entries works.
The statement gets clear when one understands the concept of inner join.
inner join creates a cross product of all entries from the tables specified.
It then checks the where condition and holds only those records for which the condition is satisfied.
Lets first take an example for cross product using sets.
We'll then move on to tables.
Consider two sets S1 and S2.
S1 = { 1, 2 , 3 }.
S2 = { 4 , 5 }
S1 Cross S2 = { 1, 4 } { 1,5} {2,4} {2,5} {3,4} {3,5}.
We will now apply the same concept to tables.
When it comes to tables , S1 , S2 will be the tables with records {1,2,3} and {4,5} respectively.
Lets take an example.
Tab1. - has two fields f1 and f2
Sory for the poor table representation. This is the best i could muster.
f1 f2
1 a
2 b
Tab2 has two fields f1 and f3
f1 f3
1 Rec1
1 Rec2
2 Rec3
The cross product is
where first two columns belong to tab1 , last two belong to tab2.
f1 f2 tab2-f1 tab2-f3
1 a 1 Rec1
1 a 1 Rec2
1 a 2 Rec3
2 b 1 Rec1
2 b 1 Rec2
2 b 2 Rec3
from the above only rows which satisfy the condition f1=tab2-f1 are selected
so only records 1 , 2 6 are selected.
f1 and tab2-f1 is merged as they are equal.
This is how select with for all entries works.
Sunday, June 10, 2007
How to print apostrophe in SAP ABAP
In one of the training sessions , the tutor posed a question..
Write a program to display apostrophe (') in ABAP program.
One of them answered , declare a text symbol of the form text-001 ,
and set its value to '.
Lateral thinking... It works.
There is a more direct way to do it too.
replce single quote with 2 single quote :-)
hers how we do it
data: LINE(20) type c.
CONCATENATE 'It''' 's Hot'.
write:/ LINE.
Hope u found this helpful.
Write a program to display apostrophe (') in ABAP program.
One of them answered , declare a text symbol of the form text-001 ,
and set its value to '.
Lateral thinking... It works.
There is a more direct way to do it too.
replce single quote with 2 single quote :-)
hers how we do it
data: LINE(20) type c.
CONCATENATE 'It''' 's Hot'.
write:/ LINE.
Hope u found this helpful.
Tuesday, April 3, 2007
Impersonation-Runas
here goes the problem , Get a username , password and executable file name.
Run in the context of the specified user. The program should work on windows 2000 , 2003 and xp ...
I first thought .. easyyy .. then i said not that easyyy .. and then i realised i underestimated the problem ..
This is my thought process flow ...
Impersonate and Create Process:
Use LogonUser , get the user's token.
ImersonateLoggedOnUser
Then call CreateProcess...
Thoroughly mistaken dear ,....
CreateProcess runs the process in the security context of the primary token of the thread...
ImpersonateLoggedOnUser creates an impersonation thread.
This method will not work...
CreateProcessAsUser:
Use LogonUser , get the users token
Call CreateProcessAsUser with the token obtained from the above step.
I found the method good mainly because i need not store the password once i get the token.
I ran the program , Boooom CreateProcessAsUser failed with "The Client Does Not Hold A required Privilege"
Here is the catch ... The process that calls CreateProcessAsUser should have
"Act as part of the operating system" (SeTcbPrivilege)
"Bypass traverse checking" (SeChangeNotifyPrivilege)
"Increase quotas" (SeIncreaseQuotaPrivilege)
"Replace a process level token" (SeAssignPrimaryTokenPrivilege)
Huh ... Even the administrator does not have these privileges !!!!
I thought whats the use ?? Forget it ....
CreateProcessWithLogonW:
This does not require any special privilege.. Thanks ..
It takes username and password and does the logging internally.
The user should have log on locally permission ..
Not bad..
Now this creates a new console and there is no way ( i know of ) to prevent it ...
So i sought to hiding the new window.
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
DWORD ret = 0;
memset(&sInfo, 0, sizeof(sInfo));
memset(&pInfo, 0, sizeof(pInfo));
sInfo.cb = sizeof(sInfo);
// do not display the new window
sInfo.dwFlags = STARTF_USESHOWWINDOW ;
sInfo.wShowWindow = SW_HIDE;
Great , no window appears now :-) .. But hey how am i suposed to know what the process has done ... I need to log it somewhere ...
I was thinking about logging the output to a file..
Here is how to go about it
// create the redirection handle
// this handle is used for output
SECURITY_ATTRIBUTES secAttr;
secAttr.nLength = sizeof ( secAttr);
secAttr.lpSecurityDescriptor = NULL;
secAttr.bInheritHandle = TRUE;
HANDLE rOutput = CreateFile (
_T("LogFile.log"),
FILE_ALL_ACCESS,
FILE_SHARE_READ,
&secAttr,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL // template file
);
// open always return ERROR_ALREADY_EXISTS even though function succeeds
if ( (0!= (retVal = GetLastError())) && ERROR_ALREADY_EXISTS != retVal )
{
printError ( retVal , _T("Unable To create log file") );
goto cleanup;
}
// to append to specified file
if ( INVALID_SET_FILE_POINTER == SetFilePointer ( rOutput , 0 , NULL , FILE_END ) )
{
printError ( retVal , _T("Unable To Set Log Append") );
goto cleanup;
}
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
DWORD ret = 0;
memset(&sInfo, 0, sizeof(sInfo));
memset(&pInfo, 0, sizeof(pInfo));
sInfo.cb = sizeof(sInfo);
// set the handles in startup info
// do not display the new window
sInfo.dwFlags = STARTF_USESHOWWINDOW STARTF_USESTDHANDLES ;
sInfo.wShowWindow = SW_HIDE;
sInfo.hStdOutput = rOutput;
sInfo.hStdError = rOutput;
sInfo.hStdInput = GetStdHandle( STD_INPUT_HANDLE ) ;
LPTSTR wrkDir = _wgetcwd ( NULL , 0 );
ret = CreateProcessWithLogonW(
c_usrName, // user name
c_fDom?c_DomName:NULL, // domain name
c_pswd, // user pswd
LOGON_WITH_PROFILE, // login with profile , otherwise keeps asking permission for psexec
NULL, // name of program
(LPTSTR)commandString, // command line
0, // flags
NULL,
wrkDir, // new wrking dir for child process
&sInfo, // startup info
&pInfo); // process info
Problem solved
Run in the context of the specified user. The program should work on windows 2000 , 2003 and xp ...
I first thought .. easyyy .. then i said not that easyyy .. and then i realised i underestimated the problem ..
This is my thought process flow ...
Impersonate and Create Process:
Use LogonUser , get the user's token.
ImersonateLoggedOnUser
Then call CreateProcess...
Thoroughly mistaken dear ,....
CreateProcess runs the process in the security context of the primary token of the thread...
ImpersonateLoggedOnUser creates an impersonation thread.
This method will not work...
CreateProcessAsUser:
Use LogonUser , get the users token
Call CreateProcessAsUser with the token obtained from the above step.
I found the method good mainly because i need not store the password once i get the token.
I ran the program , Boooom CreateProcessAsUser failed with "The Client Does Not Hold A required Privilege"
Here is the catch ... The process that calls CreateProcessAsUser should have
"Act as part of the operating system" (SeTcbPrivilege)
"Bypass traverse checking" (SeChangeNotifyPrivilege)
"Increase quotas" (SeIncreaseQuotaPrivilege)
"Replace a process level token" (SeAssignPrimaryTokenPrivilege)
Huh ... Even the administrator does not have these privileges !!!!
I thought whats the use ?? Forget it ....
CreateProcessWithLogonW:
This does not require any special privilege.. Thanks ..
It takes username and password and does the logging internally.
The user should have log on locally permission ..
Not bad..
Now this creates a new console and there is no way ( i know of ) to prevent it ...
So i sought to hiding the new window.
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
DWORD ret = 0;
memset(&sInfo, 0, sizeof(sInfo));
memset(&pInfo, 0, sizeof(pInfo));
sInfo.cb = sizeof(sInfo);
// do not display the new window
sInfo.dwFlags = STARTF_USESHOWWINDOW ;
sInfo.wShowWindow = SW_HIDE;
Great , no window appears now :-) .. But hey how am i suposed to know what the process has done ... I need to log it somewhere ...
I was thinking about logging the output to a file..
Here is how to go about it
// create the redirection handle
// this handle is used for output
SECURITY_ATTRIBUTES secAttr;
secAttr.nLength = sizeof ( secAttr);
secAttr.lpSecurityDescriptor = NULL;
secAttr.bInheritHandle = TRUE;
HANDLE rOutput = CreateFile (
_T("LogFile.log"),
FILE_ALL_ACCESS,
FILE_SHARE_READ,
&secAttr,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL // template file
);
// open always return ERROR_ALREADY_EXISTS even though function succeeds
if ( (0!= (retVal = GetLastError())) && ERROR_ALREADY_EXISTS != retVal )
{
printError ( retVal , _T("Unable To create log file") );
goto cleanup;
}
// to append to specified file
if ( INVALID_SET_FILE_POINTER == SetFilePointer ( rOutput , 0 , NULL , FILE_END ) )
{
printError ( retVal , _T("Unable To Set Log Append") );
goto cleanup;
}
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
DWORD ret = 0;
memset(&sInfo, 0, sizeof(sInfo));
memset(&pInfo, 0, sizeof(pInfo));
sInfo.cb = sizeof(sInfo);
// set the handles in startup info
// do not display the new window
sInfo.dwFlags = STARTF_USESHOWWINDOW STARTF_USESTDHANDLES ;
sInfo.wShowWindow = SW_HIDE;
sInfo.hStdOutput = rOutput;
sInfo.hStdError = rOutput;
sInfo.hStdInput = GetStdHandle( STD_INPUT_HANDLE ) ;
LPTSTR wrkDir = _wgetcwd ( NULL , 0 );
ret = CreateProcessWithLogonW(
c_usrName, // user name
c_fDom?c_DomName:NULL, // domain name
c_pswd, // user pswd
LOGON_WITH_PROFILE, // login with profile , otherwise keeps asking permission for psexec
NULL, // name of program
(LPTSTR)commandString, // command line
0, // flags
NULL,
wrkDir, // new wrking dir for child process
&sInfo, // startup info
&pInfo); // process info
Problem solved
Subscribe to:
Posts (Atom)