i have a try to implement SMPP client , a first test is do bind after i have live socket connection.
but server show HEX Error message when receive the stream.
SMPP Unit
interface
uses Classes;
Type
// c octet strings
TSystemID = string[16];
TPassword = string[9];
TSystemType = string[13];
TAddr = string[21];
TAddr_Range = string[41];
TSvc_Type = string[6];
TDate_time = string[17];
TMsgID = string[65];
pPDU_HDR = ^TPDU_HDR;
TPDU_HDR = packed record
command_len : LongWord ;
command_id : LongWord ;
command_status :LongWord ;
command_number:LongWord ;
end;
pSMPP_BIND = ^TSMPP_BIND ;
TSMPP_BIND = packed record
SystemID : TSystemID ;
Password : TPassword ;
SystemType : TSystemType ;
Ver : Byte;
Addr_TON : Byte ;
Addr_NPI : Byte ;
Addr_Range : TAddr_Range ;
end;
const
{ max short message length }
DCS7_MAX_LEN = 160;
DCS8_MAX_LEN = 140;
DCSUCS2_MAX_LEN = DCS8_MAX_LEN div 2;
{ command ids }
cmdNull = $00000000;
cmdBindReceiver = $00000001;
cmdBindTransmitter = $00000002;
cmdQuery = $00000003;
cmdReplace = $00000007;
cmdCancel = $00000008;
cmdBindTransceiver = $00000009;
cmdOutbind = $0000000B;
cmdUnbind = $00000006;
cmdSubmitSM = $00000004;
cmdDeliverSM = $00000005;
cmdEnquireLink = $00000015;
cmdSubmitMultiply = $00000021;
cmdAlertNotification = $00000102;
cmdData = $00000103;
cmdGenericNack = $80000000;
cmdResponseBase = $80000000;
cmdBindReceiverResponse = $80000001;
cmdBindTransmitterResponse = $80000002;
cmdQueryResponse = $80000003;
cmdReplaceResponse = $80000007;
cmdCancelResponse = $80000008;
cmdBindTransceiverResponse = $80000009;
cmdUnbindResponse = $80000006;
cmdSubmitSMResponse = $80000004;
cmdDeliverSMResponse = $80000005;
cmdEnquireLinkResponse = $80000015;
cmdSubmitMultiplyResponse = $80000021;
cmdDataResponse = $80000103;
{ ESM_CLASS }
ESM_CLASS_DELIVERY_RECEIPT = $04;
ESM_CLASS_UDHI = $40;
implementation
end.
ON My Form btnSendBindClick
procedure TFrmMain.btnSendBindClick(Sender: TObject);
var hdr : TPDU_HDR ;
bind_pkt : TSMPP_BIND ;
mm : TMemoryStream ;
HdrPtr : pPDU_HDR ;
BindPtr : pSMPP_BIND ;
sysid : AnsiString ;
pass : AnsiString ;
systype : AnsiString ;
add_rn : AnsiString ;
begin
sysid := 'sysid';
pass := 'pass';
systype := 'sys_type';
add_rn := '';
hdr.command_id := htonl(cmdBindTransceiver) ;
hdr.command_status := htonl(cmdNull) ;
hdr.command_number := htonl(cmdBindTransmitter) ;
hdr.command_len := htonl(SizeOf(hdr)+SizeOf(bind_pkt));
bind_pkt.SystemID := pansiChar(sysid);
bind_pkt.Password := pansiChar(pass);
bind_pkt.SystemType := pansiChar(systype);
bind_pkt.Ver := 0 ;
bind_pkt.Addr_TON := 1 ;
bind_pkt.Addr_NPI := 1 ;
bind_pkt.Addr_Range := pansiChar(add_rn);
HdrPtr := #HdrPtr ;
BindPtr := #bind_pkt ;
mm := TMemoryStream.Create ;
mm.Write(HdrPtr^,SizeOf(hdr));
mm.Position := mm.Size;
mm.Write(BindPtr^,SizeOf(bind_pkt));
mm.Position := 0 ;
clnt.Socket.SendStream(mm);
end;
I think i need to encode data stream to something, but i am not sure .
I worked with SMPP in 1999/2000 last time, but at that time, specs. 3.4 said that fields like SystemID, Password etc..., i.e. declared as Var. Max nn, are of type C-OctetString.
So if the spec did not change, you completelly missed it: you cannot use records and similiar data structures, but you have to create an octet stream containing sequence of ASCIIZ strings with no padding, e.g. (using Delphi syntax): ...'SystemId'#0'Password'#0'SystemType'#0.... And if I remember it correctly, you should change endians for integer fields as well.
Related
Call procedure from C#:
DataSet ds = new DataSet();
using (OracleConnection con = new OracleConnection(WebConfigurationManager.ConnectionStrings["DataContext"].ConnectionString))
{
using (OracleCommand cmd = new OracleCommand("CS_SERVICEREQUEST_PUB.GET_SR_NOTES_DETAILS", con))
{
con.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
OracleParameter p_api_version = cmd.Parameters.Add("p_api_version", OracleDbType.Int32);
p_api_version.Direction = ParameterDirection.Input;
p_api_version.Value = 4;
OracleParameter p_incident_id = cmd.Parameters.Add("p_incident_id", OracleDbType.Int32);
p_incident_id.Direction = ParameterDirection.Input;
p_incident_id.Value = 860636;
OracleParameter p_incident_number = cmd.Parameters.Add("p_incident_number", OracleDbType.Varchar2, 50);
p_incident_number.Direction = ParameterDirection.Input;
p_incident_number.Value = "480777";
OracleParameter x_notes = cmd.Parameters.Add("x_notes", null); // having issue with this
x_notes.Direction = ParameterDirection.Output;
OracleParameter x_return_status = cmd.Parameters.Add("x_return_status", OracleDbType.Varchar2, 50);
x_return_status.Direction = ParameterDirection.Output;
OracleParameter x_msg_count = cmd.Parameters.Add("x_msg_count", OracleDbType.Varchar2, 50);
x_msg_count.Direction = ParameterDirection.Output;
OracleParameter x_msg_data = cmd.Parameters.Add("x_msg_data", OracleDbType.Varchar2, 50);
x_msg_data.Direction = ParameterDirection.Output;
using (OracleTransaction tran = con.BeginTransaction(IsolationLevel.ReadCommitted))
{
try
{
cmd.Transaction = tran;
cmd.ExecuteNonQuery();
using (OracleDataAdapter da = new OracleDataAdapter())
{
da.SelectCommand = cmd;
da.Fill(ds);
}
tran.Commit();
}
catch (OracleException ex)
{
tran.Rollback();
}
finally
{
con.Close();
}
}
}
}
Procedure in Oracle apps:
PROCEDURE GET_SR_NOTES_DETAILS
( p_api_version IN NUMBER,
p_incident_id IN NUMBER ,
p_incident_number IN VARCHAR2,
x_notes OUT NOCOPY sr_notes_det_table,
x_return_status OUT NOCOPY VARCHAR2,
x_msg_count OUT NOCOPY VARCHAR2,
x_msg_data OUT NOCOPY VARCHAR2)
IS
l_incident_id number := null;
l_sr_found number := 1;
l_api_name VARCHAR2(100) := 'CS_SERVICEREQUEST_PUB.GET_SR_NOTES_DETAILS';
l_count NUMBER := 0;
--l_tasks tasks_table;
--l_notes notes_table;
--l_sr_rec sr_records_cur%ROWTYPE;
BEGIN
--initialize the msg count to 0
x_msg_count := 0;
x_msg_data := null;
IF (p_incident_id IS NULL) AND (p_incident_number IS NOT NULL) THEN
BEGIN
select incident_id into l_incident_id
from cs_incidents_all_b
where incident_number = p_incident_number;
EXCEPTION
WHEN NO_DATA_FOUND THEN
l_sr_found := 0;
END;
ELSE
l_incident_id := p_incident_id;
END IF;
IF l_sr_found = 1 THEN
BEGIN
select a.NOTES,
a.NOTES_DETAIL,
a.NOTE_TYPE,
a.NOTE_TYPE_MEANING,
a.NOTE_STATUS,
a.NOTE_STATUS_MEANING,
a.CREATED_BY,
a.creation_date,
a.last_update_date,
DECODE(b.employee_id,NULL,(select d.party_name from hz_parties d where d.party_id=b.person_party_id),
DECODE(b.person_party_id,NULL,NULL,(select c.FULL_NAME from hr_employees c where c.employee_id=b.employee_id))) CREATED_BY_NAME,
DECODE(b.employee_id,NULL,'CUSTOMER','AGENT') CREATED_BY_USER_TYPE,
b.PERSON_PARTY_ID CONTACT_PARTY_ID
bulk collect into x_notes
from jtf_notes_vl a,fnd_user b
where a.source_object_id=l_incident_id AND a.source_object_code='SR' AND a.created_by = b.user_id
order by a.creation_date desc;
EXCEPTION
WHEN NO_DATA_FOUND THEN
x_return_status := 'S';
END;
END IF;
x_return_status := 'S';
EXCEPTION
WHEN FND_API.G_EXC_ERROR THEN
x_return_status := FND_API.G_RET_STS_ERROR;
FND_MSG_PUB.Count_And_Get
( p_count => x_msg_count,
p_data => x_msg_data
);
WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
FND_MSG_PUB.Count_And_Get
( p_count => x_msg_count,
p_data => x_msg_data
);
WHEN OTHERS THEN
x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
FND_MSG_PUB.Add_Exc_Msg(G_PKG_NAME, l_api_name);
END IF;
FND_MSG_PUB.Count_And_Get
( p_count => x_msg_count,
p_data => x_msg_data
);
END GET_SR_NOTES_DETAILS;
--End changes for get sr related info
END CS_ServiceRequest_PUB;
Unable to call this procedure from c# because I did not find any oracledBtype which is used for
x_notes OUT NOCOPY sr_notes_det_table
Here code for sr_notes_det_table
TYPE SR_NOTES_DET_REC IS RECORD (
NOTES JTF_NOTES_VL.NOTES%TYPE ,
NOTES_DETAIL JTF_NOTES_VL.NOTES_DETAIL%TYPE ,
NOTE_TYPE JTF_NOTES_VL.NOTE_TYPE%TYPE ,
NOTE_TYPE_MEANING JTF_NOTES_VL.NOTE_TYPE_MEANING%TYPE ,
NOTE_STATUS JTF_NOTES_VL.NOTE_STATUS%TYPE ,
NOTE_STATUS_MEANING JTF_NOTES_VL.NOTE_STATUS_MEANING%TYPE ,
CREATED_BY JTF_NOTES_VL.CREATED_BY%TYPE,
CREATION_DATE JTF_NOTES_VL.CREATION_DATE%TYPE,
last_update_date JTF_NOTES_VL.last_update_date%TYPE,
CREATED_BY_NAME VARCHAR2(240),
CREATED_BY_USER_TYPE VARCHAR2(30),
CONTACT_PARTY_ID NUMBER);
TYPE sr_notes_det_table IS TABLE OF SR_NOTES_DET_REC INDEX BY BINARY_INTEGER;
in my procedure call I have only problem with this out parameter
OracleParameter x_notes = cmd.Parameters.Add("x_notes", null);
x_notes.Direction = ParameterDirection.Output;
How can I captured this output parameter value in c#. please help or guide me how can I implement this correctly into the C#.
I'm attempting to utilize Adobe Acrobat OLE to optimize and compress PDFs that we take in through various internal programs. Adobe uses C for all of their documentation, and I'm having trouble converting a structure to a record in Delphi.
Referencing the SDK here:
Adobe struct:
struct _t_PDFOptParams{
ASSize_t size;
ASPathName asPathDest;
ASFileSys fileSys;
ProgressMonitor progMon;
void* progMonClientData;
PDFOptPDFVersion enmAcrobatVersion;
PDFOptImageOptionsRec imageOptionsColor;
PDFOptImageOptionsRec imageOptionsGrayscale;
PDFOptImageOptionsRec imageOptionsMonochrome;
PDFont* arrPDFontsToUnembed;
ASInt32 cPDFontsToUnembed;
PDFOptFlattenTransparencyOptions pdfOptFlattenTransparencyOptions;
ASBool bRemoveFormActions;
ASBool bFlattenFormFields;
ASBool bRemoveJavascriptActions;
ASBool bRemoveAlternateImages;
ASBool bRemoveThumbnails;
ASBool bRemoveDocumentTags;
ASBool bSmoothenLines;
ASBool bMergeImageFragments;
ASBool bRemovePrintSettings;
ASBool bRemoveSrchIndex;
ASBool bRemoveBookmarks;
ASBool bRemoveCommentsAndWidgets;
ASBool bRemoveDocInfoAndMetadata;
ASBool bRemoveObjectData;
ASBool bRemoveFileAttachments;
ASBool bRemoveCrossRefs;
ASBool bRemovePrivateData;
ASBool bFlattenVisibleLayers;
PDFOptObjectCompression enmObjectCompression;
ASBool bUnencodedToFlate;
ASBool bLZWToFlate;
ASBool bRemoveInvalidBookmarks;
ASBool bRemoveInvalidLinks;
ASBool bRemoveUnreferencedNamedDests;
ASBool bLinearize;
}PDFOptParamsRec, *PDFOptParams;
My attempt in Delphi to create a record:
type PDFParams = record
size : byte;
asPathDest : string;
//fileSys : ;
//progMon : null
//progMonClientData : null
//enmAcrobatVersion : PDFOptPDFVersion;
//imageOptionsColor
//imageOptionsGrayscale
//imageOptionsMonochrome
//arrPDFontsToUnembed
cPDFontsToUnembed :Integer;
//pdfOptFlattenTransparencyOptions
bRemoveFormactions : bool;
bFlattenFormFields : bool;
bRemoveJavascriptActions : bool;
bRemoveAlternateImages : bool;
bRemoveThumbnails : bool;
bRemoveDocumentTags : bool;
bSmoothenLines : bool;
bMergeImageFragments : bool;
bRemovePrintSettings : bool;
bRemoveSrchIndex : bool;
bRemoveBookmarks : bool;
bRemoveCommentsAndWidgets: bool;
bRemoveDocInfoAndMetadata: bool;
bRemoveObjectData : bool;
bRemoveFileAttachments : bool;
bRemoveCrossRefs : bool;
bRemovePrivateData : bool;
bFlattenVisibleLayers : bool;
//enmObjectCompression : bool;
bUnencodedToFlate : bool;
bLZWToFlate : bool;
bRemoveInvalidBookmarks : bool;
bRemoveInvalidLinks : bool;
bRemoveUnreferencedNamedDests : bool;
bLinearize : bool;
end;
I'm not sure what I should be setting the commented out fields to?
What you have translated so far is not even close to being accurate. ASSize_t is not a single byte, ASPathName is not a string, ASBool is not a bool, etc.
The PDFOptParams struct has dependencies on a LOT of other types. Based on the PDF, the definitions of those types would look something like this:
type
{ define this manually only if your Delphi version does not already provide it }
size_t = NativeUInt;
ASSize_t = size_t;
ASInt32 = Int32;
ASUns16 = UInt16;
ASBool = ASUns16;
ASDuration = ASInt32;
ASFileMode = ASUns16;
ASMDFile = Pointer;
ASErrorCode = ASInt32;
{ the following types are not documented in the PDF, so you need
to track down what they are actually defined as in the SDK and
translate them as needed... }
_t_ASPathNameRec = record
...
end;
ASPathName = ^_t_ASPathNameRec;
_t_PDFont = record
...
end;
PDFont = ^_t_PDFont;
_t_ASTextRec = record
...
end;
ASText = ^_t_ASTextRec;
{ I'm not going to translate all of the following callback types,
I'll leave that as an exercise for you to do. I've done the 1st
two for you (note: the PDF doesn't describe calling conventions
used, so if 'cdecl' doesn't work, try 'stdcall' instead)... }
ASFileSysOpenProc = function(pathName: ASPathName; mode: ASFileMode; var fP: ASMDFile): ASErrorCode; cdecl;
ASFileSysCloseProc = function(f: ASMDFile): ASErrorCode; cdecl;
ASFileSysFlushProc = ...;
ASFileSysSetPosProc = ...;
ASFileSysGetPosProc = ...;
ASFileSysSetEofProc = ...;
ASFileSysGetEofProc = ...;
ASFileSysReadProc = ...;
ASFileSysWriteProc = ...;
ASFileSysRemoveProc = ...;
ASFileSysRenameProc = ...;
ASFileSysIsSameFileProc = ...;
ASFileSysGetNameProc = ...;
ASFileSysGetTempPathNameProc = ...;
ASFileSysCopyPathNameProc = ...;
ASFileSysDiPathFromPathProc = ...;
ASFileSysPathFromDIPathProc = ...;
ASFileSysDisposePathNameProc = ...;
ASFileSysGetFileSysNameProc = ...;
ASFileSysGetStorageFreeSpaceProc = ...;
ASFileSysFlushVolumeProc = ...;
ASFileSysGetFileFlags = ...;
ASFileSysAsyncReadProc = ...;
ASFileSysAsyncWriteProc = ...;
ASFileSysAsyncAbortProc = ...;
ASFileSysYieldProc = ...;
ASFileSysMReadRequestProc = ...;
ASFileSysGetStatusProc = ...;
ASFileSysCreatePathNameProc = ...;
ASFileSysAcquireFileSysPathProc = ...;
ASFileSysClearOutstandingMReadsProc = ...;
ASFileSysGetItemPropsProc = ...;
ASFileSysFirstFolderItemProc = ...;
ASFileSysNextFolderItemProc = ...;
ASFileSysDestroyFolderIteratorProc = ...;
ASFileSysSetModeProc = ...;
ASFileSysURLFromPathProc = ...;
ASFileSysGetParentProc = ...;
ASFileSysCreateFolderProc = ...;
ASFileSysRemoveFolderProc = ...;
ASFileSysDisplayStringFromPathProc = ...;
ASFileSysSetTypeAndCreatorProc = ...;
ASFileSysGetTypeAndCreatorProc = ...;
ASFileSysReopenProc = ...;
ASFileSysHardFlushProc = ...;
ASFileSysGetPlatformThingProc = ...;
ASFileSysGetItemPropsAsCabProc = ...;
ASFileSysCanPerformOpOnItemProc = ...;
ASFileSysPerformOpOnItemProc = ...;
ASFileSysAcquirePlatformPathProc = ...;
ASFileSysReleasePlatformPathProc = ...;
ASFileSysGetNameAsASTextProc = ...;
ASFileSysDisplayASTextFromPathProc = ...;
ASFileSysRangeArrivedProc = ...;
ASFileSysCanSetEofProc = ...;
ASFileSysDIPathFromPathExProc = ...;
ASFileSysPathFromDIPathExProc = ...;
ASFileSysGetFilePositionLimitProc = ...;
ASFileSysOpen64Proc = ...;
ASFileSysSetPos64Proc = ...;
ASFileSysGetPos64Proc = ...;
ASFileSysSetEof64Proc = ...;
ASFileSysGetEof64Proc = ...;
ASFileSysGetNameForDisplayProc = ...;
ASFileSysGetStorageFreeSpace64Proc = ...;
_t_ASFileSysRec = record
size: ASSize_t;
open: ASFileSysOpenProc;
close: ASFileSysCloseProc;
flush: ASFileSysFlushProc;
setpos: ASFileSysSetPosProc;
getpos: ASFileSysGetPosProc;
seteof: ASFileSysSetEofProc;
geteof: ASFileSysGetEofProc;
read: ASFileSysReadProc;
write: ASFileSysWriteProc;
remove: ASFileSysRemoveProc;
rename: ASFileSysRenameProc;
isSameFile: ASFileSysIsSameFileProc;
getName: ASFileSysGetNameProc;
getTempPathName: ASFileSysGetTempPathNameProc;
copyPathName: ASFileSysCopyPathNameProc;
diPathFromPath: ASFileSysDiPathFromPathProc;
pathFromDIPath: ASFileSysPathFromDIPathProc;
disposePathName: ASFileSysDisposePathNameProc;
getFileSysName: ASFileSysGetFileSysNameProc;
getStorageFreeSpace: ASFileSysGetStorageFreeSpaceProc;
flushVolume: ASFileSysFlushVolumeProc;
getFileFlags: ASFileSysGetFileFlags;
readAsync: ASFileSysAsyncReadProc;
writeAsync: ASFileSysAsyncWriteProc;
abortAsync: ASFileSysAsyncAbortProc;
yield: ASFileSysYieldProc;
mreadRequest: ASFileSysMReadRequestProc ;
getStatus: ASFileSysGetStatusProc;
createPathName: ASFileSysCreatePathNameProc;
acquireFileSysPath: ASFileSysAcquireFileSysPathProc;
clearOutstandingMReads: ASFileSysClearOutstandingMReadsProc;
getItemProps: ASFileSysGetItemPropsProc;
firstFolderItem: ASFileSysFirstFolderItemProc;
nextFolderItem: ASFileSysNextFolderItemProc;
destroyFolderIterator: ASFileSysDestroyFolderIteratorProc;
setFileMode: ASFileSysSetModeProc;
urlFromPath: ASFileSysURLFromPathProc;
getParent: ASFileSysGetParentProc;
createFolder: ASFileSysCreateFolderProc;
removeFolder: ASFileSysRemoveFolderProc;
displayStringFromPath: ASFileSysDisplayStringFromPathProc;
setTypeAndCreator: ASFileSysSetTypeAndCreatorProc;
getTypeAndCreator: ASFileSysGetTypeAndCreatorProc;
reopen: ASFileSysReopenProc;
hardFlush: ASFileSysHardFlushProc;
getPlatformThing: ASFileSysGetPlatformThingProc;
getItemPropsAsCab: ASFileSysGetItemPropsAsCabProc;
canPerformOpOnItem: ASFileSysCanPerformOpOnItemProc;
performOpOnItem: ASFileSysPerformOpOnItemProc;
acquirePlatformPath: ASFileSysAcquirePlatformPathProc;
releasePlatformPath: ASFileSysReleasePlatformPathProc;
getNameAsASText: ASFileSysGetNameAsASTextProc;
displayASTextFromPath: ASFileSysDisplayASTextFromPathProc;
rangeArrived: ASFileSysRangeArrivedProc;
canSetEof: ASFileSysCanSetEofProc;
diPathFromPathEx: ASFileSysDIPathFromPathExProc;
pathFromDIPathEx: ASFileSysPathFromDIPathExProc;
getfileposlimit: ASFileSysGetFilePositionLimitProc;
open64: ASFileSysOpen64Proc;
setpos64: ASFileSysSetPos64Proc;
getpos64: ASFileSysGetPos64Proc;
seteof64: ASFileSysSetEof64Proc;
geteof64: ASFileSysGetEof64Proc;
getNameForDisplay: ASFileSysGetNameForDisplayProc;
getStorageFreeSpace64: ASFileSysGetStorageFreeSpace64Proc;
end;
ASFileSysRec = _t_ASFileSysRec;
ASFileSys = ^_t_ASFileSysRec;
PMBeginOperationProc = procedure(clientData: Pointer); cdecl;
PMEndOperationProc = procedure(clientData: Pointer); cdecl;
PMSetDurationProc = procedure(duration: ASDuration; clientData: Pointer); cdecl;
PMSetCurrValueProc = procedure(currValue: ASDuration; clientData: Pointer); cdecl;
PMGetDurationProc = function(clientData: Pointer): ASDuration; cdecl;
PMGetCurrValueProc = function(clientData: Pointer): ASDuration;
PMSetTextProc = procedure(text: ASText; clientData: Pointer); cdecl;
_t_ProgressMonitor = record
size: ASSize_t;
beginOperation: PMBeginOperationProc;
endOperation: PMEndOperationProc;
setDuration: PMSetDurationProc;
setCurrValue: PMSetCurrValueProc;
getDuration: PMGetDurationProc;
getCurrValue: PMGetCurrValueProc;
setText: PMSetTextProc;
end;
ASProgressMonitorRec = _t_ProgressMonitor;
ASProgressMonitor = ^_t_ProgressMonitor;
ProgressMonitor = ASProgressMonitor;
PDFOptPDFVersion = (kPDFOptRetainVersion = 0, kPDFOptAcrobat4, kPDFOptAcrobat5, kPDFOptAcrobat6, kPDFOptAcrobat7, kPDFOptAcrobat8);
PDFOptDownsamplingAlgo = (kPDFOptNoDownsampling = 0, kPDFOptAverage, kPDFOptSubsampling, kPDFOptBicubic);
PDFOptCompressionAlgo = (kPDFOptNoRecompression = 0, kPDFOptJpeg2000, kPDFOptJpeg, kPDFOptFlate, kPDFOptJBIG2, kPDFOptCCITT3, kPDFOptCCITT4, kPDFOptRunLengh);
PDFOptCompressionQlty = (kPDFOptMinimumQlty = 0, kPDFOptLowQlty, kPDFOptMediumQlty, kPDFOptHighQlty, kPDFOptMaximumQlty, kPDFOptLossless);
_t_PDFOptImageOptions = record
size: ASSize_t;
enmDownsamplingAlgo: PDFOptDownsamplingAlgo;
ppiDownsampleTo: ASInt32;
ppiDownsampleAbove: ASInt32;
enmCompressionAlgo: PDFOptCompressionAlgo;
enmCompressionQlty: PDFOptCompressionQlty;
nTileSize: ASInt32;
end;
PDFOptImageOptionsRec = _t_PDFOptImageOptions;
PDFOptImageOptions = ^_t_PDFOptImageOptions;
_t_PDFOptFlattenTransparencyOptions = record
size: ASSize_t;
pctRasterVectorBalance,
ppiLineArtAndText,
ppiGradientAndMesh: ASInt32;
bConvertText,
bConvertStrokes,
bClipComplexRegions,
bPreserveOverprint: ASBool;
end;
PDFOptFlattenTransparencyOptionsRec = _t_PDFOptFlattenTransparencyOptions;
PDFOptFlattenTransparencyOptions = ^_t_PDFOptFlattenTransparencyOptions;
PDFOptObjectCompression = (kPDFOptUntouchedCompression = 0, kPDFOptFullCompression, kPDFOptPartialCompression, kPDFOptRemoveCompression);
_t_PDFOptParams = record
size: ASSize_t;
asPathDest: ASPathName;
fileSys: ASFileSys;
progMon: ProgressMonitor;
progMonClientData: Pointer;
enmAcrobatVersion: PDFOptPDFVersion;
imageOptionsColor,
imageOptionsGrayscale,
imageOptionsMonochrome: PDFOptImageOptionsRec;
arrPDFontsToUnembed: ^PDFont;
cPDFontsToUnembed: ASInt32;
pdfOptFlattenTransparencyOptions: PDFOptFlattenTransparencyOptions;
bRemoveFormActions,
bFlattenFormFields,
bRemoveJavascriptActions,
bRemoveAlternateImages,
bRemoveThumbnails,
bRemoveDocumentTags,
bSmoothenLines,
bMergeImageFragments,
bRemovePrintSettings,
bRemoveSrchIndex,
bRemoveBookmarks,
bRemoveCommentsAndWidgets,
bRemoveDocInfoAndMetadata,
bRemoveObjectData,
bRemoveFileAttachments,
bRemoveCrossRefs,
bRemovePrivateData,
bFlattenVisibleLayers: ASBool;
enmObjectCompression: PDFOptObjectCompression;
bUnencodedToFlate,
bLZWToFlate,
bRemoveInvalidBookmarks,
bRemoveInvalidLinks,
bRemoveUnreferencedNamedDests,
bLinearize: ASBool;
end;
PDFOptParamsRec = _t_PDFOptParams;
PDFOptParams = ^_t_PDFOptParams;
what is the syntax for this c++ question in Delphi?
After using an oleContainer, and trying to do SaveDocumentAs which didn't work. I thought this might be a good alternative.
update: thank you for the translation, however the excel file goes curropted after the call
var
ExcelOle: TOleContainer;
begin
ExcelOLE.CreateObjectFromFile(FileName, False);
ExcelOle.OleObject.application.workbooks[1].save;
end;
Simply create an Ole Object:
uses ComObj, Excel;
var Excel: OleVariant;
Excel := CreateOleObject('EXCEL.Application');
Excel.Application.Workbooks.Add;
Excel.Application.Workbooks[1].SaveAs('c:\test.xlsx', xlWorkbookDefault); // or xlOpenXMLWorkbook (51)
Excel.Application.Quit;
Excel.pas
unit Excel;
interface
uses Windows, Activex;
// originally from Excel97.pas
// XlFileFormat constants
type
XlFileFormat = TOleEnum;
const
xlAddIn = $00000012;
xlCSV = $00000006;
xlCSVMac = $00000016;
xlCSVMSDOS = $00000018;
xlCSVWindows = $00000017;
xlDBF2 = $00000007;
xlDBF3 = $00000008;
xlDBF4 = $0000000B;
xlDIF = $00000009;
xlExcel2 = $00000010;
xlExcel2FarEast = $0000001B;
xlExcel3 = $0000001D;
xlExcel4 = $00000021;
xlExcel5 = $00000027;
xlExcel7 = $00000027;
xlExcel9795 = $0000002B;
xlExcel4Workbook = $00000023;
xlIntlAddIn = $0000001A;
xlIntlMacro = $00000019;
xlWorkbookNormal = $FFFFEFD1;
xlSYLK = $00000002;
xlTemplate = $00000011;
xlCurrentPlatformText = $FFFFEFC2;
xlTextMac = $00000013;
xlTextMSDOS = $00000015;
xlTextPrinter = $00000024;
xlTextWindows = $00000014;
xlWJ2WD1 = $0000000E;
xlWK1 = $00000005;
xlWK1ALL = $0000001F;
xlWK1FMT = $0000001E;
xlWK3 = $0000000F;
xlWK4 = $00000026;
xlWK3FM3 = $00000020;
xlWKS = $00000004;
xlWorks2FarEast = $0000001C;
xlWQ1 = $00000022;
xlWJ3 = $00000028;
xlWJ3FJ3 = $00000029;
xlExcel12 =50;
xlExcel8 = 56;
xlHtml = 44;
xlOpenXMLAddIn = 55;
xlOpenXMLTemplate = 54;
xlOpenXMLTemplateMacroEnabled = 53;
xlOpenXMLWorkbook = 51;
xlOpenXMLWorkbookMacroEnabled = 52;
xlTemplate8 = 17;
xlUnicodeText = 42;
xlWebArchive = 45;
xlWorkbookDefault = 51;
xlXMLSpreadsheet = 46;
implementation
end.
I am working on a COM Object library with function that returns a VARIANT with a SAFEARRAY of BSTRs. How can I display the values from this VARIANT instance and save it inside a TStringList? I tried searching the net with no clear answer.
I tried the following with no success:
Variant V;
String mystr;
VarClear(V);
TVarData(V).VType = varOleStr;
V = ComFunction->GetValues(); //<<<<----- V is empty
mystr = (wchar_t *)(TVarData(V).VString);
Memo1->Lines->Add(mystr);
VarClear(V);
You can use TWideStringDynArray and let Delphi do the conversion:
procedure LoadStringsFromVariant(const Values: TWideStringDynArray; Strings: TStrings);
var
I: Integer;
begin
Strings.BeginUpdate;
try
for I := Low(Values) to High(Values) do
Strings.Add(Values[I]);
finally
Strings.EndUpdate;
end;
end;
When you call this with your Variant safearray of BSTRs it will be converted to TWideStringDynArray automatically. An incompatible Variant will cause the runtime error EVariantInvalidArgError.
To check if a Variant holds a safe array of BSTR you can do this:
IsOK := VarIsArray(V) and (VarArrayDimCount(V) = 1) and (VarType(V) and varTypeMask = varOleStr);
uses ActiveX;
var
VSafeArray: PSafeArray;
LBound, UBound, I: LongInt;
W: WideString;
begin
VSafeArray := ComFunction.GetValues();
SafeArrayGetLBound(VSafeArray, 1, LBound);
SafeArrayGetUBound(VSafeArray, 1, UBound);
for I := LBound to UBound do
begin
SafeArrayGetElement(VSafeArray, I, W);
Memo1.Lines.Add(W);
end;
SafeArrayDestroy(VSafeArray); // cleanup PSafeArray
if you are creating ComFunction via late binding (CreateOleObject) you should use:
var
v: Variant;
v := ComFunction.GetValues;
for i := VarArrayLowBound(v, 1) to VarArrayHighBound(v, 1) do
begin
W := VarArrayGet(v, [i]);
Memo1.Lines.Add (W);
end;
How can I display the values from this VARIANT instance and save it inside a TStringList?
The COM VARIANT struct has parray and pparray data members that are pointers to a SAFEARRAY, eg:
VARIANT V;
LPSAFEARRAY sa = V_ISBYREF(&V) ? V_ARRAYREF(&V) : V_ARRAY(&V);
The VCL Variant class, on the other hand, has an LPSAFEARRAY conversion operator defined, so you can assign it directly (but only if the Variant.VType field that not have the varByRef flag present, that is), eg:
Variant V;
LPSAFEARRAY sa = V;
Either way, once you have the SAFEARRAY pointer, use the SafeArray API to access the BSTR values, eg:
bool __fastcall VariantToStrings(const Variant &V, TStrings *List)
{
// make sure the Variant is holding an array
if (!V_ISARRAY(&V)) return false;
// get the array pointer
LPSAFEARRAY sa = V_ISBYREF(&V) ? V_ARRAYREF(&V) : V_ARRAY(&V);
// make sure the array is holding BSTR values
VARTYPE vt;
if (FAILED(SafeArrayGetVartype(sa, &vt))) return false;
if (vt != VT_BSTR) return false;
// make sure the array has only 1 dimension
if (SafeArrayGetDim(sa) != 1) return false;
// get the bounds of the array's sole dimension
LONG lBound = -1, uBound = -1;
if (FAILED(SafeArrayGetLBound(sa, 0, &lBound))) return false;
if (FAILED(SafeArrayGetUBound(sa, 0, &uBound))) return false;
if ((lBound > -1) && (uBound > -1))
{
// access the raw data of the array
BSTR *values = NULL;
if (FAILED(SafeArrayAccessData(sa, (void**)&values))) return false;
try
{
List->BeginUpdate();
try
{
// loop through the array adding the elements to the list
for (LONG idx = lBound; l <= uBound; ++idx)
{
String s;
if (values[idx] != NULL)
s = String(values[idx], SysStringLen(values[idx]));
List->Add(s);
}
}
__finally
{
List->EndUpdate();
}
}
__finally
{
// unaccess the raw data of the array
SafeArrayUnaccessData(sa);
}
}
return true;
}
VarClear(V);
TVarData(V).VType = varOleStr;
You don't need those at all. The VCL Variant class initializes itself to a blank state, and there is no need to assign the VType since you are assigning a new value to the entire Variant immediately afterwards.
V = ComFunction->GetValues(); //<<<<----- V is empty
If V is empty, then GetValues() is returning an empty Variant to begin with.
mystr = (wchar_t *)(TVarData(V).VString);
TVarData::VString is an AnsiString& reference, not a wchar_t* pointer. To convert a VCL Variant (not a COM VARIANT) to a String, just assign it as-is and let the RTL works out the detail for you:
String mystr = V;
I'm working on a PE Loader, just like windows loader
my target is an executable not DLL,i tried first loadlibrary but faced reallocation problems,got some code to fix it, but it didn't work with all targets (some exe's needs to be loaded at the same BaseAdress to work probably
so i got to the point, i've to implement my loader to ensure the BaseAddress issue and no need for reallocation
I'm forcing my application to load at a high addr(0x10000000),while using VirtualAlloc to allocate memory for headers & sections for the target app
i use VirtualQuery to see the state of the address i want to allocate, if not free i use UnMapViewOfFile if Page type MEM_MAPPED else VirtualFree(MEM_RELEASE)
The problem is that if the memory pages are MEM_MAPPED & MEM_COMMIT (always page file backed pages) all methods fails with error code 0x57 ERROR_INVALID_PARAMETER
looking for solutions/ideas here's the code :
MylpAddr = (DWORD)lpAddr ;
MemInfo.RegionSize = 0 ;
NtUnmapViewOfSection= (NTUNMAPVIEWOFSECTION)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtUnmapViewOfSection");
NtProtectVirtualMemory= (NTPROTECTVIRTUALMEMORY)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtProtectVirtualMemory");
NtUnlockVirtualMemory= (NTUNLOCKVIRTUALMEMORY)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtUnlockVirtualMemory");
GetSystemInfo(&siSysInfo);
szPage = siSysInfo.dwPageSize ;
i = VirtualQuery( (LPCVOID)MylpAddr , &MemInfo , 0x20 ) ;
if (!i) return NULL ;
if ( !(MemInfo.State & MEM_FREE) )
{
if ( MemInfo.Type & MEM_MAPPED )
{
hProc = GetCurrentProcess() ;
szPage = MemInfo.RegionSize ;
i = NtUnlockVirtualMemory(hProc , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , LOCK_VM_IN_WORKING_SET | LOCK_VM_IN_RAM );
i = NtProtectVirtualMemory(hProc , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , PAGE_READWRITE , &OldProt ) ;
i = NtUnmapViewOfSection( hProc , (LPVOID)MemInfo.AllocationBase );
i = UnmapViewOfFile( (LPVOID)MemInfo.AllocationBase );
if (!i) i =1 ;
}
else
{
j = VirtualUnlock(MemInfo.BaseAddress , MemInfo.RegionSize);
i = VirtualFree( (LPVOID)MemInfo.AllocationBase , NULL , MEM_RELEASE ) ;
}
if (!i) return NULL ;
}
MylpAddr = (DWORD)VirtualAlloc( lpAddr , dwSize , AllocType , ProtFlags );
Sorry for bringing up such an old question, I just thought it might help someone.
As far as I know, to fork a process you must have used CreateProcess function. Therefore you need to use VirtualQueryEx and VirtualAllocEx instead of VirtualQuery and VirtualAlloc. Also replace hProc value with a handle to your created process. I also noticed that you have explicitly used 0x20 as dwLength that you probably need to change it with dwSize.In summary:
PROCESS_INFORMATION piProcessInformation;
ZeroMemory(&piProcessInformation,sizeof(PROCESS_INFORMATION));
if(CreateProcess(NULL,processName,NULL,NULL,false,CREATE_SUSPENDED,NULL,NULL,&suStartUpInformation,&piProcessInformation))
{
cContext.ContextFlags = CONTEXT_FULL;
GetThreadContext(piProcessInformation.hThread,&cContext);
i = VirtualQueryEx(piProcessInformation.hProcess, (LPCVOID)MylpAddr , &MemInfo , dwSize ) ;
if (!i) return NULL ;
if ( !(MemInfo.State & MEM_FREE) )
{
if ( MemInfo.Type & MEM_MAPPED )
{
// hProc = GetCurrentProcess() ; No need to this line
szPage = MemInfo.RegionSize ;
i = NtUnlockVirtualMemory(piProcessInformation.hProcess , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , LOCK_VM_IN_WORKING_SET | LOCK_VM_IN_RAM );
i = NtProtectVirtualMemory(piProcessInformation.hProcess , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , PAGE_READWRITE , &OldProt ) ;
i = NtUnmapViewOfSection( piProcessInformation.hProcess , (LPVOID)MemInfo.AllocationBase );
i = UnmapViewOfFile( (LPVOID)MemInfo.AllocationBase );
if (!i) i =1 ;
}
else
{
j = VirtualUnlock(MemInfo.BaseAddress , MemInfo.RegionSize);
i = VirtualFreeEx(piProcessInformation.hProcess, (LPVOID)MemInfo.AllocationBase , NULL , MEM_RELEASE ) ;
}
if (!i) return NULL ;
}
MylpAddr = (DWORD)VirtualAllocEx(piProcessInformation.hProcess, lpAddr , dwSize , AllocType , ProtFlags );
}