sysutils.pp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for EMX
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. Dos;
  20. {$DEFINE HAS_SLEEP}
  21. { used OS file system APIs use ansistring }
  22. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  23. { OS has an ansistring/single byte environment variable API }
  24. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  25. { Include platform independent interface part }
  26. {$i sysutilh.inc}
  27. implementation
  28. uses
  29. sysconst;
  30. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  31. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  32. { Include platform independent implementation part }
  33. {$i sysutils.inc}
  34. {****************************************************************************
  35. System (imported) calls
  36. ****************************************************************************}
  37. (* "uses DosCalls" could not be used here due to type *)
  38. (* conflicts, so needed parts had to be redefined here). *)
  39. type
  40. TFileStatus = object
  41. end;
  42. PFileStatus = ^TFileStatus;
  43. TFileStatus3 = object (TFileStatus)
  44. DateCreation, {Date of file creation.}
  45. TimeCreation, {Time of file creation.}
  46. DateLastAccess, {Date of last access to file.}
  47. TimeLastAccess, {Time of last access to file.}
  48. DateLastWrite, {Date of last modification of file.}
  49. TimeLastWrite:word; {Time of last modification of file.}
  50. FileSize, {Size of file.}
  51. FileAlloc:cardinal; {Amount of space the file really
  52. occupies on disk.}
  53. AttrFile:cardinal; {Attributes of file.}
  54. end;
  55. PFileStatus3=^TFileStatus3;
  56. TFileStatus4=object(TFileStatus3)
  57. cbList:cardinal; {Length of entire EA set.}
  58. end;
  59. PFileStatus4=^TFileStatus4;
  60. TFileStatus3L = object (TFileStatus)
  61. DateCreation, {Date of file creation.}
  62. TimeCreation, {Time of file creation.}
  63. DateLastAccess, {Date of last access to file.}
  64. TimeLastAccess, {Time of last access to file.}
  65. DateLastWrite, {Date of last modification of file.}
  66. TimeLastWrite:word; {Time of last modification of file.}
  67. FileSize, {Size of file.}
  68. FileAlloc:int64; {Amount of space the file really
  69. occupies on disk.}
  70. AttrFile:cardinal; {Attributes of file.}
  71. end;
  72. PFileStatus3L=^TFileStatus3L;
  73. TFileStatus4L=object(TFileStatus3L)
  74. cbList:cardinal; {Length of entire EA set.}
  75. end;
  76. PFileStatus4L=^TFileStatus4L;
  77. TFileFindBuf3=object(TFileStatus)
  78. NextEntryOffset: cardinal; {Offset of next entry}
  79. DateCreation, {Date of file creation.}
  80. TimeCreation, {Time of file creation.}
  81. DateLastAccess, {Date of last access to file.}
  82. TimeLastAccess, {Time of last access to file.}
  83. DateLastWrite, {Date of last modification of file.}
  84. TimeLastWrite:word; {Time of last modification of file.}
  85. FileSize, {Size of file.}
  86. FileAlloc:cardinal; {Amount of space the file really
  87. occupies on disk.}
  88. AttrFile:cardinal; {Attributes of file.}
  89. Name:shortstring; {Also possible to use as ASCIIZ.
  90. The byte following the last string
  91. character is always zero.}
  92. end;
  93. PFileFindBuf3=^TFileFindBuf3;
  94. TFileFindBuf4=object(TFileStatus)
  95. NextEntryOffset: cardinal; {Offset of next entry}
  96. DateCreation, {Date of file creation.}
  97. TimeCreation, {Time of file creation.}
  98. DateLastAccess, {Date of last access to file.}
  99. TimeLastAccess, {Time of last access to file.}
  100. DateLastWrite, {Date of last modification of file.}
  101. TimeLastWrite:word; {Time of last modification of file.}
  102. FileSize, {Size of file.}
  103. FileAlloc:cardinal; {Amount of space the file really
  104. occupies on disk.}
  105. AttrFile:cardinal; {Attributes of file.}
  106. cbList:longint; {Size of the file's extended attributes.}
  107. Name:shortstring; {Also possible to use as ASCIIZ.
  108. The byte following the last string
  109. character is always zero.}
  110. end;
  111. PFileFindBuf4=^TFileFindBuf4;
  112. TFileFindBuf3L=object(TFileStatus)
  113. NextEntryOffset: cardinal; {Offset of next entry}
  114. DateCreation, {Date of file creation.}
  115. TimeCreation, {Time of file creation.}
  116. DateLastAccess, {Date of last access to file.}
  117. TimeLastAccess, {Time of last access to file.}
  118. DateLastWrite, {Date of last modification of file.}
  119. TimeLastWrite:word; {Time of last modification of file.}
  120. FileSize, {Size of file.}
  121. FileAlloc:int64; {Amount of space the file really
  122. occupies on disk.}
  123. AttrFile:cardinal; {Attributes of file.}
  124. Name:shortstring; {Also possible to use as ASCIIZ.
  125. The byte following the last string
  126. character is always zero.}
  127. end;
  128. PFileFindBuf3L=^TFileFindBuf3L;
  129. TFileFindBuf4L=object(TFileStatus)
  130. NextEntryOffset: cardinal; {Offset of next entry}
  131. DateCreation, {Date of file creation.}
  132. TimeCreation, {Time of file creation.}
  133. DateLastAccess, {Date of last access to file.}
  134. TimeLastAccess, {Time of last access to file.}
  135. DateLastWrite, {Date of last modification of file.}
  136. TimeLastWrite:word; {Time of last modification of file.}
  137. FileSize, {Size of file.}
  138. FileAlloc:int64; {Amount of space the file really
  139. occupies on disk.}
  140. AttrFile:cardinal; {Attributes of file.}
  141. cbList:cardinal; {Size of the file's extended attributes.}
  142. Name:shortstring; {Also possible to use as ASCIIZ.
  143. The byte following the last string
  144. character is always zero.}
  145. end;
  146. PFileFindBuf4L=^TFileFindBuf4L;
  147. TFSInfo = record
  148. case word of
  149. 1:
  150. (File_Sys_ID,
  151. Sectors_Per_Cluster,
  152. Total_Clusters,
  153. Free_Clusters: cardinal;
  154. Bytes_Per_Sector: word);
  155. 2: {For date/time description,
  156. see file searching realted
  157. routines.}
  158. (Label_Date, {Date when volume label was created.}
  159. Label_Time: word; {Time when volume label was created.}
  160. VolumeLabel: ShortString); {Volume label. Can also be used
  161. as ASCIIZ, because the byte
  162. following the last character of
  163. the string is always zero.}
  164. end;
  165. PFSInfo = ^TFSInfo;
  166. TCountryCode=record
  167. Country, {Country to query info about (0=current).}
  168. CodePage: cardinal; {Code page to query info about (0=current).}
  169. end;
  170. PCountryCode=^TCountryCode;
  171. TTimeFmt = (Clock12, Clock24);
  172. TCountryInfo=record
  173. Country, CodePage: cardinal; {Country and codepage requested.}
  174. case byte of
  175. 0:
  176. (DateFormat: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  177. CurrencyUnit: array [0..4] of char;
  178. ThousandSeparator: char; {Thousands separator.}
  179. Zero1: byte; {Always zero.}
  180. DecimalSeparator: char; {Decimals separator,}
  181. Zero2: byte;
  182. DateSeparator: char; {Date separator.}
  183. Zero3: byte;
  184. TimeSeparator: char; {Time separator.}
  185. Zero4: byte;
  186. CurrencyFormat, {Bit field:
  187. Bit 0: 0=indicator before value
  188. 1=indicator after value
  189. Bit 1: 1=insert space after
  190. indicator.
  191. Bit 2: 1=Ignore bit 0&1, replace
  192. decimal separator with
  193. indicator.}
  194. DecimalPlace: byte; {Number of decimal places used in
  195. currency indication.}
  196. TimeFormat: TTimeFmt; {12/24 hour.}
  197. Reserve1: array [0..1] of word;
  198. DataSeparator: char; {Data list separator}
  199. Zero5: byte;
  200. Reserve2: array [0..4] of word);
  201. 1:
  202. (fsDateFmt: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  203. szCurrency: array [0..4] of char;
  204. {null terminated currency symbol}
  205. szThousandsSeparator: array [0..1] of char;
  206. {Thousands separator + #0}
  207. szDecimal: array [0..1] of char;
  208. {Decimals separator + #0}
  209. szDateSeparator: array [0..1] of char;
  210. {Date separator + #0}
  211. szTimeSeparator: array [0..1] of char;
  212. {Time separator + #0}
  213. fsCurrencyFmt, {Bit field:
  214. Bit 0: 0=indicator before value
  215. 1=indicator after value
  216. Bit 1: 1=insert space after
  217. indicator.
  218. Bit 2: 1=Ignore bit 0&1, replace
  219. decimal separator with
  220. indicator}
  221. cDecimalPlace: byte; {Number of decimal places used in
  222. currency indication}
  223. fsTimeFmt: byte; {0=12,1=24 hours}
  224. abReserved1: array [0..1] of word;
  225. szDataSeparator: array [0..1] of char;
  226. {Data list separator + #0}
  227. abReserved2: array [0..4] of word);
  228. end;
  229. PCountryInfo=^TCountryInfo;
  230. TRequestData=record
  231. PID, {ID of process that wrote element.}
  232. Data: cardinal; {Information from process writing the data.}
  233. end;
  234. PRequestData=^TRequestData;
  235. {Queue data structure for synchronously started sessions.}
  236. TChildInfo = record
  237. case boolean of
  238. false:
  239. (SessionID,
  240. Return: word); {Return code from the child process.}
  241. true:
  242. (usSessionID,
  243. usReturn: word); {Return code from the child process.}
  244. end;
  245. PChildInfo = ^TChildInfo;
  246. TStartData=record
  247. {Note: to omit some fields, use a length smaller than SizeOf(TStartData).}
  248. Length:word; {Length, in bytes, of datastructure
  249. (24/30/32/50/60).}
  250. Related:word; {Independent/child session (0/1).}
  251. FgBg:word; {Foreground/background (0/1).}
  252. TraceOpt:word; {No trace/trace this/trace all (0/1/2).}
  253. PgmTitle:PChar; {Program title.}
  254. PgmName:PChar; {Filename to program.}
  255. PgmInputs:PChar; {Command parameters (nil allowed).}
  256. TermQ:PChar; {System queue. (nil allowed).}
  257. Environment:PChar; {Environment to pass (nil allowed).}
  258. InheritOpt:word; {Inherit environment from shell/
  259. inherit environment from parent (0/1).}
  260. SessionType:word; {Auto/full screen/window/presentation
  261. manager/full screen Dos/windowed Dos
  262. (0/1/2/3/4/5/6/7).}
  263. Iconfile:PChar; {Icon file to use (nil allowed).}
  264. PgmHandle:cardinal; {0 or the program handle.}
  265. PgmControl:word; {Bitfield describing initial state
  266. of windowed sessions.}
  267. InitXPos,InitYPos:word; {Initial top coordinates.}
  268. InitXSize,InitYSize:word; {Initial size.}
  269. Reserved:word;
  270. ObjectBuffer:PChar; {If a module cannot be loaded, its
  271. name will be returned here.}
  272. ObjectBuffLen:cardinal; {Size of your buffer.}
  273. end;
  274. PStartData=^TStartData;
  275. const
  276. ilStandard = 1; (* Use TFileStatus3/TFindFileBuf3 *)
  277. ilQueryEASize = 2; (* Use TFileStatus4/TFindFileBuf4 *)
  278. ilQueryEAs = 3;
  279. ilQueryFullName = 5;
  280. ilStandardL = 11; (* Use TFileStatus3L/TFindFileBuf3L *)
  281. ilQueryEASizeL = 12; (* Use TFileStatus4L/TFindFileBuf4L *)
  282. ilQueryEAsL = 13;
  283. quFIFO = 0;
  284. quLIFO = 1;
  285. quPriority = 2;
  286. quNoConvert_Address = 0;
  287. quConvert_Address = 4;
  288. {Start the new session independent or as a child.}
  289. ssf_Related_Independent = 0; {Start new session independent
  290. of the calling session.}
  291. ssf_Related_Child = 1; {Start new session as a child
  292. session to the calling session.}
  293. {Start the new session in the foreground or in the background.}
  294. ssf_FgBg_Fore = 0; {Start new session in foreground.}
  295. ssf_FgBg_Back = 1; {Start new session in background.}
  296. {Should the program started in the new session
  297. be executed under conditions for tracing?}
  298. ssf_TraceOpt_None = 0; {No trace.}
  299. ssf_TraceOpt_Trace = 1; {Trace with no notification
  300. of descendants.}
  301. ssf_TraceOpt_TraceAll = 2; {Trace all descendant sessions.
  302. A termination queue must be
  303. supplied and Related must be
  304. ssf_Related_Child (=1).}
  305. {Will the new session inherit open file handles
  306. and environment from the calling process.}
  307. ssf_InhertOpt_Shell = 0; {Inherit from the shell.}
  308. ssf_InhertOpt_Parent = 1; {Inherit from the calling process.}
  309. {Specifies the type of session to start.}
  310. ssf_Type_Default = 0; {Use program's type.}
  311. ssf_Type_FullScreen = 1; {OS/2 full screen.}
  312. ssf_Type_WindowableVIO = 2; {OS/2 window.}
  313. ssf_Type_PM = 3; {Presentation Manager.}
  314. ssf_Type_VDM = 4; {DOS full screen.}
  315. ssf_Type_WindowedVDM = 7; {DOS window.}
  316. {Additional values for Windows programs}
  317. Prog_31_StdSeamlessVDM = 15; {Windows 3.1 program in its
  318. own windowed session.}
  319. Prog_31_StdSeamlessCommon = 16; {Windows 3.1 program in a
  320. common windowed session.}
  321. Prog_31_EnhSeamlessVDM = 17; {Windows 3.1 program in enhanced
  322. compatibility mode in its own
  323. windowed session.}
  324. Prog_31_EnhSeamlessCommon = 18; {Windows 3.1 program in enhanced
  325. compatibility mode in a common
  326. windowed session.}
  327. Prog_31_Enh = 19; {Windows 3.1 program in enhanced
  328. compatibility mode in a full
  329. screen session.}
  330. Prog_31_Std = 20; {Windows 3.1 program in a full
  331. screen session.}
  332. {Specifies the initial attributes for a OS/2 window or DOS window session.}
  333. ssf_Control_Visible = 0; {Window is visible.}
  334. ssf_Control_Invisible = 1; {Window is invisible.}
  335. ssf_Control_Maximize = 2; {Window is maximized.}
  336. ssf_Control_Minimize = 4; {Window is minimized.}
  337. ssf_Control_NoAutoClose = 8; {Window will not close after
  338. the program has ended.}
  339. ssf_Control_SetPos = 32768; {Use InitXPos, InitYPos,
  340. InitXSize, and InitYSize for
  341. the size and placement.}
  342. {This is the correct way to call external assembler procedures.}
  343. procedure syscall;external name '___SYSCALL';
  344. function DosSetFileInfo (Handle: THandle; InfoLevel: cardinal; AFileStatus: PFileStatus;
  345. FileStatusLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 218;
  346. function DosQueryFSInfo (DiskNum, InfoLevel: cardinal; var Buffer: TFSInfo;
  347. BufLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 278;
  348. function DosQueryFileInfo (Handle: THandle; InfoLevel: cardinal;
  349. AFileStatus: PFileStatus; FileStatusLen: cardinal): cardinal; cdecl;
  350. external 'DOSCALLS' index 279;
  351. function DosScanEnv (Name: PChar; var Value: PChar): cardinal; cdecl;
  352. external 'DOSCALLS' index 227;
  353. function DosFindFirst (FileMask: PChar; var Handle: THandle; Attrib: cardinal;
  354. AFileStatus: PFileStatus; FileStatusLen: cardinal;
  355. var Count: cardinal; InfoLevel: cardinal): cardinal; cdecl;
  356. external 'DOSCALLS' index 264;
  357. function DosFindNext (Handle: THandle; AFileStatus: PFileStatus;
  358. FileStatusLen: cardinal; var Count: cardinal): cardinal; cdecl;
  359. external 'DOSCALLS' index 265;
  360. function DosFindClose (Handle: THandle): cardinal; cdecl;
  361. external 'DOSCALLS' index 263;
  362. function DosQueryCtryInfo (Size: cardinal; var Country: TCountryCode;
  363. var Res: TCountryInfo; var ActualSize: cardinal): cardinal; cdecl;
  364. external 'NLS' index 5;
  365. function DosMapCase (Size: cardinal; var Country: TCountryCode;
  366. AString: PChar): cardinal; cdecl; external 'NLS' index 7;
  367. procedure DosSleep (MSec: cardinal); cdecl; external 'DOSCALLS' index 229;
  368. function DosCreateQueue (var Handle: THandle; Priority:longint;
  369. Name: PChar): cardinal; cdecl;
  370. external 'QUECALLS' index 16;
  371. function DosReadQueue (Handle: THandle; var ReqBuffer: TRequestData;
  372. var DataLen: cardinal; var DataPtr: pointer;
  373. Element, Wait: cardinal; var Priority: byte;
  374. ASem: THandle): cardinal; cdecl;
  375. external 'QUECALLS' index 9;
  376. function DosCloseQueue (Handle: THandle): cardinal; cdecl;
  377. external 'QUECALLS' index 11;
  378. function DosStartSession (var AStartData: TStartData;
  379. var SesID, PID: cardinal): cardinal; cdecl;
  380. external 'SESMGR' index 37;
  381. function DosFreeMem(P:pointer):cardinal; cdecl; external 'DOSCALLS' index 304;
  382. {****************************************************************************
  383. File Functions
  384. ****************************************************************************}
  385. const
  386. ofRead = $0000; {Open for reading}
  387. ofWrite = $0001; {Open for writing}
  388. ofReadWrite = $0002; {Open for reading/writing}
  389. doDenyRW = $0010; {DenyAll (no sharing)}
  390. faCreateNew = $00010000; {Create if file does not exist}
  391. faOpenReplace = $00040000; {Truncate if file exists}
  392. faCreate = $00050000; {Create if file does not exist, truncate otherwise}
  393. FindResvdMask = $00003737; {Allowed bits in attribute
  394. specification for DosFindFirst call.}
  395. {$ASMMODE INTEL}
  396. function FileOpen (const FileName: pointer; Mode: integer): longint; assembler;
  397. asm
  398. push ebx
  399. {$IFDEF REGCALL}
  400. mov ecx, edx
  401. mov edx, eax
  402. {$ELSE REGCALL}
  403. mov ecx, Mode
  404. mov edx, FileName
  405. {$ENDIF REGCALL}
  406. (* DenyNone if sharing not specified. *)
  407. mov eax, ecx
  408. xor eax, 112
  409. jz @FOpenDefSharing
  410. cmp eax, 64
  411. jbe FOpen1
  412. @FOpenDefSharing:
  413. or ecx, 64
  414. @FOpen1:
  415. mov eax, 7F2Bh
  416. call syscall
  417. (* syscall __open() returns -1 in case of error, i.e. exactly what we need *)
  418. pop ebx
  419. end {['eax', 'ebx', 'ecx', 'edx']};
  420. function FileOpen (const FileName: rawbytestring; Mode: integer): longint;
  421. var
  422. SystemFileName: RawByteString;
  423. begin
  424. SystemFileName := ToSingleByteFileSystemEncodedFileName(FileName);
  425. FileOpen := FileOpen(pointer(SystemFileName),Mode);
  426. end;
  427. function FileCreate (const FileName: RawByteString): longint;
  428. begin
  429. FileCreate := FileCreate (FileName, ofReadWrite or faCreate or doDenyRW, 777);
  430. (* Sharing to DenyAll *)
  431. end;
  432. function FileCreate (const FileName: RawByteString; Rights: integer): longint;
  433. begin
  434. FileCreate := FileCreate (FileName, ofReadWrite or faCreate or doDenyRW,
  435. Rights); (* Sharing to DenyAll *)
  436. end;
  437. function FileCreate (const FileName: Pointer; ShareMode: integer; Rights: integer): longint; assembler;
  438. asm
  439. push ebx
  440. {$IFDEF REGCALL}
  441. mov ecx, edx
  442. mov edx, eax
  443. {$ELSE REGCALL}
  444. mov ecx, ShareMode
  445. mov edx, FileName
  446. {$ENDIF REGCALL}
  447. and ecx, 112
  448. or ecx, ecx
  449. jz @FCDefSharing
  450. cmp ecx, 64
  451. jbe @FCSharingOK
  452. @FCDefSharing:
  453. mov ecx, doDenyRW (* Sharing to DenyAll *)
  454. @FCSharingOK:
  455. or ecx, ofReadWrite or faCreate
  456. mov eax, 7F2Bh
  457. call syscall
  458. pop ebx
  459. end {['eax', 'ebx', 'ecx', 'edx']};
  460. function FileCreate (const FileName: RawByteString; ShareMode: integer; Rights: integer): longint;
  461. var
  462. SystemFileName: RawByteString;
  463. begin
  464. SystemFileName := ToSingleByteFileSystemEncodedFileName(FileName);
  465. FileOpen := FileCreate(pointer(SystemFileName),ShareMode,Rights);
  466. end;
  467. function FileRead (Handle: longint; Out Buffer; Count: longint): longint;
  468. assembler;
  469. asm
  470. push ebx
  471. {$IFDEF REGCALL}
  472. mov ebx, eax
  473. {$ELSE REGCALL}
  474. mov ebx, Handle
  475. mov ecx, Count
  476. mov edx, Buffer
  477. {$ENDIF REGCALL}
  478. mov eax, 3F00h
  479. call syscall
  480. jnc @FReadEnd
  481. mov eax, -1
  482. @FReadEnd:
  483. pop ebx
  484. end {['eax', 'ebx', 'ecx', 'edx']};
  485. function FileWrite (Handle: longint; const Buffer; Count: longint): longint;
  486. assembler;
  487. asm
  488. push ebx
  489. {$IFDEF REGCALL}
  490. mov ebx, eax
  491. {$ELSE REGCALL}
  492. mov ebx, Handle
  493. mov ecx, Count
  494. mov edx, Buffer
  495. {$ENDIF REGCALL}
  496. mov eax, 4000h
  497. call syscall
  498. jnc @FWriteEnd
  499. mov eax, -1
  500. @FWriteEnd:
  501. pop ebx
  502. end {['eax', 'ebx', 'ecx', 'edx']};
  503. function FileSeek (Handle, FOffset, Origin: longint): longint; assembler;
  504. asm
  505. push ebx
  506. {$IFDEF REGCALL}
  507. mov ebx, eax
  508. mov eax, ecx
  509. {$ELSE REGCALL}
  510. mov ebx, Handle
  511. mov eax, Origin
  512. mov edx, FOffset
  513. {$ENDIF REGCALL}
  514. mov ah, 42h
  515. call syscall
  516. jnc @FSeekEnd
  517. mov eax, -1
  518. @FSeekEnd:
  519. pop ebx
  520. end {['eax', 'ebx', 'edx']};
  521. function FileSeek (Handle: longint; FOffset: Int64; Origin: longint): Int64;
  522. begin
  523. {$warning need to add 64bit call }
  524. Result:=FileSeek(Handle,Longint(Foffset),Longint(Origin));
  525. end;
  526. procedure FileClose (Handle: longint);
  527. begin
  528. if (Handle > 4) or ((os_mode = osOS2) and (Handle > 2)) then
  529. asm
  530. push ebx
  531. mov eax, 3E00h
  532. mov ebx, Handle
  533. call syscall
  534. pop ebx
  535. end ['eax'];
  536. end;
  537. function FileTruncate (Handle: THandle; Size: Int64): boolean; assembler;
  538. asm
  539. push ebx
  540. {$IFDEF REGCALL}
  541. mov ebx, eax
  542. {$ELSE REGCALL}
  543. mov ebx, Handle
  544. {$ENDIF REGCALL}
  545. mov edx, dword ptr Size
  546. mov eax, dword ptr Size+4
  547. or eax, eax
  548. mov eax, 0
  549. jz @FTruncEnd (* file sizes > 4 GB not supported with EMX *)
  550. mov eax, 7F25h
  551. push ebx
  552. call syscall
  553. pop ebx
  554. jc @FTruncEnd
  555. mov eax, 4202h
  556. mov edx, 0
  557. call syscall
  558. mov eax, 0
  559. jnc @FTruncEnd
  560. dec eax
  561. @FTruncEnd:
  562. pop ebx
  563. end {['eax', 'ebx', 'ecx', 'edx']};
  564. function FileAge (const FileName: RawByteString): longint;
  565. var Handle: longint;
  566. begin
  567. Handle := FileOpen (FileName, 0);
  568. if Handle <> -1 then
  569. begin
  570. Result := FileGetDate (Handle);
  571. FileClose (Handle);
  572. end
  573. else
  574. Result := -1;
  575. end;
  576. function FileExists (const FileName: RawByteString): boolean;
  577. var
  578. L: longint;
  579. begin
  580. { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
  581. if FileName = '' then
  582. Result := false
  583. else
  584. begin
  585. L := FileGetAttr (FileName);
  586. Result := (L >= 0) and (L and (faDirectory or faVolumeID) = 0);
  587. (* Neither VolumeIDs nor directories are files. *)
  588. end;
  589. end;
  590. type
  591. TRec = record
  592. T, D: word;
  593. end;
  594. PSearchRec = ^SearchRec;
  595. Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
  596. var
  597. SystemEncodedPath: RawByteString;
  598. SR: PSearchRec;
  599. FStat: PFileFindBuf3L;
  600. Count: cardinal;
  601. Err: cardinal;
  602. begin
  603. if os_mode = osOS2 then
  604. begin
  605. SystemEncodedPath:=ToSingleByteEncodedFileName(Path);
  606. New (FStat);
  607. Rslt.FindHandle := THandle ($FFFFFFFF);
  608. Count := 1;
  609. if FSApi64 then
  610. Err := DosFindFirst (PChar (SystemEncodedPath), Rslt.FindHandle,
  611. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandardL)
  612. else
  613. Err := DosFindFirst (PChar (SystemEncodedPath), Rslt.FindHandle,
  614. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard);
  615. if (Err = 0) and (Count = 0) then
  616. Err := 18;
  617. FindFirst := -Err;
  618. if Err = 0 then
  619. begin
  620. Rslt.ExcludeAttr := 0;
  621. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  622. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  623. if FSApi64 then
  624. begin
  625. Rslt.Size := FStat^.FileSize;
  626. Name := FStat^.Name;
  627. Rslt.Attr := FStat^.AttrFile;
  628. end
  629. else
  630. begin
  631. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  632. Name := PFileFindBuf3 (FStat)^.Name;
  633. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  634. end;
  635. SetCodePage(Name, DefaultFileSystemCodePage, false);
  636. end
  637. else
  638. FindClose (Rslt);
  639. Dispose (FStat);
  640. end
  641. else
  642. begin
  643. Err := DOS.DosError;
  644. GetMem (SR, SizeOf (SearchRec));
  645. Rslt.FindHandle := longint(SR);
  646. DOS.FindFirst (Path, Attr, SR^);
  647. FindFirst := -DOS.DosError;
  648. if DosError = 0 then
  649. begin
  650. Rslt.Time := SR^.Time;
  651. (* Extend the supported file sizes from 2 GB to 4 GB at least. *)
  652. Rslt.Size := cardinal (SR^.Size);
  653. Rslt.Attr := SR^.Attr;
  654. Rslt.ExcludeAttr := 0;
  655. Name := SR^.Name;
  656. SetCodePage(Name, DefaultFileSystemCodePage, false);
  657. end;
  658. DOS.DosError := Err;
  659. end;
  660. end;
  661. Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
  662. var
  663. SR: PSearchRec;
  664. FStat: PFileFindBuf3L;
  665. Count: cardinal;
  666. Err: cardinal;
  667. begin
  668. if os_mode = osOS2 then
  669. begin
  670. New (FStat);
  671. Count := 1;
  672. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^), Count);
  673. if (Err = 0) and (Count = 0) then
  674. Err := 18;
  675. FindNext := -Err;
  676. if Err = 0 then
  677. begin
  678. Rslt.ExcludeAttr := 0;
  679. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  680. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  681. if FSApi64 then
  682. begin
  683. Rslt.Size := FStat^.FileSize;
  684. Name := FStat^.Name;
  685. Rslt.Attr := FStat^.AttrFile;
  686. end
  687. else
  688. begin
  689. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  690. Name := PFileFindBuf3 (FStat)^.Name;
  691. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  692. end;
  693. SetCodePage(Name, DefaultFileSystemCodePage, false);
  694. end;
  695. Dispose (FStat);
  696. end
  697. else
  698. begin
  699. SR := PSearchRec (Rslt.FindHandle);
  700. if SR <> nil then
  701. begin
  702. DOS.FindNext (SR^);
  703. FindNext := -DosError;
  704. if DosError = 0 then
  705. begin
  706. Rslt.Time := SR^.Time;
  707. (* Extend the supported file sizes from 2 GB to 4 GB at least. *)
  708. Rslt.Size := cardinal (SR^.Size);
  709. Rslt.Attr := SR^.Attr;
  710. Rslt.ExcludeAttr := 0;
  711. Name := SR^.Name;
  712. SetCodePage(Name, DefaultFileSystemCodePage, false);
  713. end;
  714. end;
  715. end;
  716. end;
  717. Procedure InternalFindClose(var Handle: THandle);
  718. var SR: PSearchRec;
  719. begin
  720. if os_mode = osOS2 then
  721. begin
  722. DosFindClose (Handle);
  723. end
  724. else
  725. begin
  726. SR := PSearchRec (Handle);
  727. DOS.FindClose (SR^);
  728. FreeMem (SR, SizeOf (SearchRec));
  729. end;
  730. Handle := 0;
  731. end;
  732. function FileGetDate (Handle: longint): longint; assembler;
  733. asm
  734. push ebx
  735. {$IFDEF REGCALL}
  736. mov ebx, eax
  737. {$ELSE REGCALL}
  738. mov ebx, Handle
  739. {$ENDIF REGCALL}
  740. mov ax, 5700h
  741. call syscall
  742. mov eax, -1
  743. jc @FGetDateEnd
  744. mov ax, dx
  745. shld eax, ecx, 16
  746. @FGetDateEnd:
  747. pop ebx
  748. end {['eax', 'ebx', 'ecx', 'edx']};
  749. function FileSetDate (Handle, Age: longint): longint;
  750. var FStat: PFileStatus3;
  751. RC: cardinal;
  752. begin
  753. if os_mode = osOS2 then
  754. begin
  755. New (FStat);
  756. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  757. SizeOf (FStat^));
  758. if RC <> 0 then
  759. FileSetDate := -1
  760. else
  761. begin
  762. FStat^.DateLastAccess := Hi (Age);
  763. FStat^.DateLastWrite := Hi (Age);
  764. FStat^.TimeLastAccess := Lo (Age);
  765. FStat^.TimeLastWrite := Lo (Age);
  766. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  767. SizeOf (FStat^));
  768. if RC <> 0 then
  769. FileSetDate := -1
  770. else
  771. FileSetDate := 0;
  772. end;
  773. Dispose (FStat);
  774. end
  775. else
  776. asm
  777. push ebx
  778. mov ax, 5701h
  779. mov ebx, Handle
  780. mov cx, word ptr [Age]
  781. mov dx, word ptr [Age + 2]
  782. call syscall
  783. jnc @FSetDateEnd
  784. mov eax, -1
  785. @FSetDateEnd:
  786. mov Result, eax
  787. pop ebx
  788. end ['eax', 'ecx', 'edx'];
  789. end;
  790. function FileGetAttr (const FileName: string): longint; assembler;
  791. asm
  792. {$IFDEF REGCALL}
  793. mov edx, eax
  794. {$ELSE REGCALL}
  795. mov edx, FileName
  796. {$ENDIF REGCALL}
  797. mov ax, 4300h
  798. call syscall
  799. jnc @FGetAttrEnd
  800. mov eax, -1
  801. @FGetAttrEnd:
  802. end {['eax', 'edx']};
  803. function FileSetAttr (const Filename: RawByteString; Attr: longint): longint;
  804. var
  805. SystemFileName: RawByteString;
  806. begin
  807. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
  808. asm
  809. mov ecx, Attr
  810. mov edx, SystemFileName
  811. mov ax, 4301h
  812. call syscall
  813. mov @result, 0
  814. jnc @FSetAttrEnd
  815. mov @result, -1
  816. @FSetAttrEnd:
  817. end ['eax', 'ecx', 'edx'];
  818. end;
  819. function DeleteFile (const FileName: string): boolean;
  820. var
  821. SystemFileName: RawByteString;
  822. begin
  823. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
  824. asm
  825. mov edx, SystemFileName
  826. mov ax, 4100h
  827. call syscall
  828. mov @result, 0
  829. jc @FDeleteEnd
  830. moc @result, 1
  831. @FDeleteEnd:
  832. end ['eax', 'edx'];
  833. end;
  834. function RenameFile (const OldName, NewName: string): boolean;
  835. var
  836. OldSystemFileName, NewSystemFileName: RawByteString;
  837. Begin
  838. OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
  839. NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
  840. asm
  841. mov edx, OldSystemFileName
  842. mov edi, NewSystemFileName
  843. mov ax, 5600h
  844. call syscall
  845. mov @result, 0
  846. jc @FRenameEnd
  847. mov @result, 1
  848. @FRenameEnd:
  849. end ['eax', 'edx', 'edi'];
  850. end;
  851. {****************************************************************************
  852. Disk Functions
  853. ****************************************************************************}
  854. {$ASMMODE ATT}
  855. function DiskFree (Drive: byte): int64;
  856. var FI: TFSinfo;
  857. RC: cardinal;
  858. begin
  859. if (os_mode = osDOS) or (os_mode = osDPMI) then
  860. {Function 36 is not supported in OS/2.}
  861. asm
  862. pushl %ebx
  863. movb Drive,%dl
  864. movb $0x36,%ah
  865. call syscall
  866. cmpw $-1,%ax
  867. je .LDISKFREE1
  868. mulw %cx
  869. mulw %bx
  870. shll $16,%edx
  871. movw %ax,%dx
  872. movl $0,%eax
  873. xchgl %edx,%eax
  874. jmp .LDISKFREE2
  875. .LDISKFREE1:
  876. cltd
  877. .LDISKFREE2:
  878. popl %ebx
  879. leave
  880. ret
  881. end
  882. else
  883. {In OS/2, we use the filesystem information.}
  884. begin
  885. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  886. if RC = 0 then
  887. DiskFree := int64 (FI.Free_Clusters) *
  888. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  889. else
  890. DiskFree := -1;
  891. end;
  892. end;
  893. function DiskSize (Drive: byte): int64;
  894. var FI: TFSinfo;
  895. RC: cardinal;
  896. begin
  897. if (os_mode = osDOS) or (os_mode = osDPMI) then
  898. {Function 36 is not supported in OS/2.}
  899. asm
  900. pushl %ebx
  901. movb Drive,%dl
  902. movb $0x36,%ah
  903. call syscall
  904. movw %dx,%bx
  905. cmpw $-1,%ax
  906. je .LDISKSIZE1
  907. mulw %cx
  908. mulw %bx
  909. shll $16,%edx
  910. movw %ax,%dx
  911. movl $0,%eax
  912. xchgl %edx,%eax
  913. jmp .LDISKSIZE2
  914. .LDISKSIZE1:
  915. cltd
  916. .LDISKSIZE2:
  917. popl %ebx
  918. leave
  919. ret
  920. end
  921. else
  922. {In OS/2, we use the filesystem information.}
  923. begin
  924. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  925. if RC = 0 then
  926. DiskSize := int64 (FI.Total_Clusters) *
  927. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  928. else
  929. DiskSize := -1;
  930. end;
  931. end;
  932. function DirectoryExists (const Directory: RawByteString): boolean;
  933. var
  934. L: longint;
  935. begin
  936. { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
  937. if Directory = '' then
  938. Result := false
  939. else
  940. begin
  941. if ((Length (Directory) = 2) or
  942. (Length (Directory) = 3) and
  943. (Directory [3] in AllowDirectorySeparators)) and
  944. (Directory [2] in AllowDriveSeparators) and
  945. (UpCase (Directory [1]) in ['A'..'Z']) then
  946. (* Checking attributes for 'x:' is not possible but for 'x:.' it is. *)
  947. L := FileGetAttr (Directory + '.')
  948. else if (Directory [Length (Directory)] in AllowDirectorySeparators) and
  949. (Length (Directory) > 1) and
  950. (* Do not remove '\' in '\\' (invalid path, possibly broken UNC path). *)
  951. not (Directory [Length (Directory) - 1] in AllowDirectorySeparators) then
  952. L := FileGetAttr (Copy (Directory, 1, Length (Directory) - 1))
  953. else
  954. L := FileGetAttr (Directory);
  955. Result := (L > 0) and (L and faDirectory = faDirectory);
  956. end;
  957. end;
  958. {****************************************************************************
  959. Time Functions
  960. ****************************************************************************}
  961. {$ASMMODE INTEL}
  962. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  963. asm
  964. (* Expects the default record alignment (word)!!! *)
  965. push edi
  966. {$IFDEF REGCALL}
  967. push eax
  968. {$ENDIF REGCALL}
  969. mov ah, 2Ah
  970. call syscall
  971. {$IFDEF REGCALL}
  972. pop eax
  973. {$ELSE REGCALL}
  974. mov edi, SystemTime
  975. {$ENDIF REGCALL}
  976. mov ax, cx
  977. stosw
  978. xor eax, eax
  979. mov al, 10
  980. mul dl
  981. shl eax, 16
  982. mov al, dh
  983. stosd
  984. push edi
  985. mov ah, 2Ch
  986. call syscall
  987. pop edi
  988. xor eax, eax
  989. mov al, cl
  990. shl eax, 16
  991. mov al, ch
  992. stosd
  993. mov al, dl
  994. shl eax, 16
  995. mov al, dh
  996. stosd
  997. pop edi
  998. end {['eax', 'ecx', 'edx', 'edi']};
  999. {$asmmode default}
  1000. {****************************************************************************
  1001. Misc Functions
  1002. ****************************************************************************}
  1003. procedure Beep;
  1004. begin
  1005. end;
  1006. {****************************************************************************
  1007. Locale Functions
  1008. ****************************************************************************}
  1009. procedure InitAnsi;
  1010. var I: byte;
  1011. Country: TCountryCode;
  1012. begin
  1013. for I := 0 to 255 do
  1014. UpperCaseTable [I] := Chr (I);
  1015. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  1016. if os_mode = osOS2 then
  1017. begin
  1018. FillChar (Country, SizeOf (Country), 0);
  1019. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  1020. end
  1021. else
  1022. begin
  1023. (* !!! TODO: DOS/DPMI mode support!!! *)
  1024. end;
  1025. for I := 0 to 255 do
  1026. if UpperCaseTable [I] <> Chr (I) then
  1027. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  1028. end;
  1029. procedure InitInternational;
  1030. var Country: TCountryCode;
  1031. CtryInfo: TCountryInfo;
  1032. Size: cardinal;
  1033. RC: cardinal;
  1034. begin
  1035. Size := 0;
  1036. FillChar (Country, SizeOf (Country), 0);
  1037. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  1038. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  1039. if RC = 0 then
  1040. begin
  1041. DateSeparator := CtryInfo.DateSeparator;
  1042. case CtryInfo.DateFormat of
  1043. 1: begin
  1044. ShortDateFormat := 'd/m/y';
  1045. LongDateFormat := 'dd" "mmmm" "yyyy';
  1046. end;
  1047. 2: begin
  1048. ShortDateFormat := 'y/m/d';
  1049. LongDateFormat := 'yyyy" "mmmm" "dd';
  1050. end;
  1051. 3: begin
  1052. ShortDateFormat := 'm/d/y';
  1053. LongDateFormat := 'mmmm" "dd" "yyyy';
  1054. end;
  1055. end;
  1056. TimeSeparator := CtryInfo.TimeSeparator;
  1057. DecimalSeparator := CtryInfo.DecimalSeparator;
  1058. ThousandSeparator := CtryInfo.ThousandSeparator;
  1059. CurrencyFormat := CtryInfo.CurrencyFormat;
  1060. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  1061. end;
  1062. InitAnsi;
  1063. InitInternationalGeneric;
  1064. end;
  1065. function SysErrorMessage(ErrorCode: Integer): String;
  1066. begin
  1067. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  1068. end;
  1069. {****************************************************************************
  1070. OS Utils
  1071. ****************************************************************************}
  1072. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  1073. begin
  1074. GetEnvironmentVariable := GetEnvPChar (EnvVar);
  1075. end;
  1076. Function GetEnvironmentVariableCount : Integer;
  1077. begin
  1078. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  1079. GetEnvironmentVariableCount := EnvC;
  1080. end;
  1081. Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  1082. begin
  1083. Result:=FPCGetEnvStrFromP (EnvP, Index);
  1084. end;
  1085. {$ASMMODE INTEL}
  1086. procedure Sleep (Milliseconds: cardinal);
  1087. begin
  1088. if os_mode = osOS2 then DosSleep (Milliseconds) else
  1089. asm
  1090. mov edx, Milliseconds
  1091. mov eax, 7F30h
  1092. call syscall
  1093. end ['eax', 'edx'];
  1094. end;
  1095. {$ASMMODE DEFAULT}
  1096. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString;Flags:TExecuteFlags=[]):
  1097. integer;
  1098. var
  1099. HQ: THandle;
  1100. SPID, STID, QName: shortstring;
  1101. SD: TStartData;
  1102. SID, PID: cardinal;
  1103. RD: TRequestData;
  1104. PCI: PChildInfo;
  1105. CISize: cardinal;
  1106. Prio: byte;
  1107. E: EOSError;
  1108. CommandLine: ansistring;
  1109. begin
  1110. if os_Mode = osOS2 then
  1111. begin
  1112. FillChar (SD, SizeOf (SD), 0);
  1113. SD.Length := 24;
  1114. SD.Related := ssf_Related_Child;
  1115. SD.PgmName := PChar (Path);
  1116. SD.PgmInputs := PChar (ComLine);
  1117. Str (GetProcessID, SPID);
  1118. Str (ThreadID, STID);
  1119. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  1120. SD.TermQ := @QName [1];
  1121. Result := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  1122. if Result = 0 then
  1123. begin
  1124. Result := DosStartSession (SD, SID, PID);
  1125. if (Result = 0) or (Result = 457) then
  1126. begin
  1127. Result := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  1128. if Result = 0 then
  1129. begin
  1130. Result := PCI^.Return;
  1131. DosCloseQueue (HQ);
  1132. DosFreeMem (PCI);
  1133. Exit;
  1134. end;
  1135. end;
  1136. DosCloseQueue (HQ);
  1137. end;
  1138. if ComLine = '' then
  1139. CommandLine := Path
  1140. else
  1141. CommandLine := Path + ' ' + ComLine;
  1142. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, Result]);
  1143. E.ErrorCode := Result;
  1144. raise E;
  1145. end else
  1146. begin
  1147. Dos.Exec (Path, ComLine);
  1148. if DosError <> 0 then
  1149. begin
  1150. if ComLine = '' then
  1151. CommandLine := Path
  1152. else
  1153. CommandLine := Path + ' ' + ComLine;
  1154. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, DosError]);
  1155. E.ErrorCode := DosError;
  1156. raise E;
  1157. end;
  1158. ExecuteProcess := DosExitCode;
  1159. end;
  1160. end;
  1161. function ExecuteProcess (const Path: AnsiString;
  1162. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  1163. var
  1164. CommandLine: AnsiString;
  1165. I: integer;
  1166. begin
  1167. Commandline := '';
  1168. for I := 0 to High (ComLine) do
  1169. if Pos (' ', ComLine [I]) <> 0 then
  1170. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1171. else
  1172. CommandLine := CommandLine + ' ' + Comline [I];
  1173. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  1174. end;
  1175. {****************************************************************************
  1176. Initialization code
  1177. ****************************************************************************}
  1178. Initialization
  1179. InitExceptions; { Initialize exceptions. OS independent }
  1180. InitInternational; { Initialize internationalization settings }
  1181. Finalization
  1182. DoneExceptions;
  1183. end.