Running 64 bit console application from a 32 bit Delphi GUI app?

I want to improve the usability of a 64 bit command line program so it
can be handled by fairly inexperienced users.
For this I need a normal Delphi program to have data specifiers etc,
which in the end results in a command file for the console
application.
This is no big deal.

The problem is the following:
------------------------------
1) Can I start the 64 bit console app in Windows7X64 using the
CreateProcess API like I am used to for 32 bit applications?
Or are 64 bit programs different?

2) And if that is possible, can I somehow snatch what it sends to
standard out (the console) and show this in the GUI application while
keeping the console minimized? How could that be done in such case?

What I want to do with the last part is show the output in a built-in
console but also analyze the output such that errors and such can be
grabbed and handled.
--

Bo Berglund
Developer in Sweden
0
Bo
8/23/2012 9:28:30 PM
embarcadero.delphi.ide 3925 articles. 0 followers. Follow

6 Replies
2386 Views

Similar Articles

[PageSpeed] 31

it's been awhile but i used something like this along time ago..

http://www.delphipages.com/forum/archive/index.php/t-84171.html

Can give it a try and see if close.. i don't have xe2 to try out. But did with D7 and win7 64bit cmd.exe
and that way worked.
0
steven
8/24/2012 1:48:49 AM
Bo wrote:

> 1) Can I start the 64 bit console app in Windows7X64 using the
> CreateProcess API like I am used to for 32 bit applications?

Yes.

> 2) And if that is possible, can I somehow snatch what it sends to
> standard out (the console) and show this in the GUI application while
> keeping the console minimized? How could that be done in such case?

CreateProcess() allows you to redirect stdin, stdout, and stderr of the spawned 
process, via the members of the STARTUPINFO record, but I don't know if that 
works between a 32-bit process and a 64-bit process due to differences in 
handle sizes.  You can try it and see what happens, though.

--
Remy Lebeau (TeamB)
0
Remy
8/24/2012 5:21:03 PM
On Thu, 23 Aug 2012 18:48:49 -0700, steven chesser <> wrote:

>it's been awhile but i used something like this along time ago..
>
>http://www.delphipages.com/forum/archive/index.php/t-84171.html
>
>Can give it a try and see if close.. i don't have xe2 to try out. But did with D7 and win7 64bit cmd.exe
>and that way worked.

The 4th message (from midiman) on this page contained code, which I
tested with some modifications to the GUI part.
For example there are extra blank chars retrieved with the
FProcess.ReadStrFromChild() call as observed by the OP too. But a
simple Trim() removes those and then a check for blank content before
adding the read line to the memo is all that is required to block the
extra data.

Worked fine as far as I could see by a quick test.
Except of course that the example command (cmd /c dir /s) returned
strange characters instead of the decimal point in the file length
display. Not to worry, I will fix that if it returns.

My target 64 bit application was compiled using Visual Studio 2012 (it
is a C++ program) and it ran well enough to make me go forward on this
track!

Thanks for the pointer, most valuable!

--

Bo Berglund
Developer in Sweden
0
Bo
8/29/2012 9:00:22 AM
On Fri, 24 Aug 2012 10:21:03 -0700, Remy Lebeau (TeamB)
<no.spam@no.spam.com> wrote:

>Bo wrote:
>
>> 1) Can I start the 64 bit console app in Windows7X64 using the
>> CreateProcess API like I am used to for 32 bit applications?
>
>Yes.
>
>> 2) And if that is possible, can I somehow snatch what it sends to
>> standard out (the console) and show this in the GUI application while
>> keeping the console minimized? How could that be done in such case?
>
>CreateProcess() allows you to redirect stdin, stdout, and stderr of the spawned 
>process, via the members of the STARTUPINFO record, but I don't know if that 
>works between a 32-bit process and a 64-bit process due to differences in 
>handle sizes.  You can try it and see what happens, though.

Remy,
yes that is used and works also to a 64 bit application.
The example in the link given by Steven works fine as in my case there
will not be any user input sent to the process, I just want to watch
the data in my GUI wrapper window.

By having a GUI front end to the command line application I can make
sure that execution needs are satisfied before launching the process.
Like changing dir to it, preparing data folders needed by the program,
making the proper command line switches and ini files etc.

All of which today has to be done by reading a paper manual and typing
away in the command window.....

(I wonder why I always wind up with these screwy old programs that
need to be maintained and/or improved?)

Thanks as always for your pointers and help, much appreciated!
--

Bo Berglund
Developer in Sweden
0
Bo
8/29/2012 9:07:02 AM
Bo Berglund wrote:

> On Fri, 24 Aug 2012 10:21:03 -0700, Remy Lebeau (TeamB)
> <no.spam@no.spam.com> wrote:
> 
> > Bo wrote:
> > 
> >> 1) Can I start the 64 bit console app in Windows7X64 using the
> >> CreateProcess API like I am used to for 32 bit applications?
> > 
> > Yes.
> > 
> >> 2) And if that is possible, can I somehow snatch what it sends to
> >> standard out (the console) and show this in the GUI application
> while >> keeping the console minimized? How could that be done in
> such case?
> > 
> > CreateProcess() allows you to redirect stdin, stdout, and stderr of
> > the spawned process, via the members of the STARTUPINFO record, but
> > I don't know if that works between a 32-bit process and a 64-bit
> > process due to differences in handle sizes.  You can try it and see
> > what happens, though.
> 
> Remy,
> yes that is used and works also to a 64 bit application.
> The example in the link given by Steven works fine as in my case there
> will not be any user input sent to the process, I just want to watch
> the data in my GUI wrapper window.
> 
> (I wonder why I always wind up with these screwy old programs that
> need to be maintained and/or improved?)
> 
That's called 'reputation'.   
Once they find someone with the tenacity to solve these problems, they
just keep coming back <bg>
0
Malcolm
8/29/2012 10:12:37 AM
On Wed, 29 Aug 2012 02:07:02 -0700, Bo Berglund
<bo.berglund@nospam.com> wrote:

>>CreateProcess() allows you to redirect stdin, stdout, and stderr of the spawned 
>>process, via the members of the STARTUPINFO record, but I don't know if that 
>>works between a 32-bit process and a 64-bit process due to differences in 
>>handle sizes.  You can try it and see what happens, though.
>
>Remy,
>yes that is used and works also to a 64 bit application.
>The example in the link given by Steven works fine as in my case there
>will not be any user input sent to the process, I just want to watch
>the data in my GUI wrapper window.

Turns out that on closer inspection it does not work as well as I had
hoped for...
There are extra lines in the memo and sometimes I see lines being
combined (losing the line ending) and even be in the wrong sequence...
So there is something very strange about this

I also discovered a very similar thread in the NativeAPI forum so I
give this link as a reference to that:
https://forums.embarcadero.com/thread.jspa?threadID=75839&tstart=0

Unfortunately example code there is only referencing C++ and MSDN KB
articles (also for C++)....

Is there a way to modify the code example linked to by Steven Chesser
such that it handles the reception of StdOut by itself and perhaps
fires an event (OnStdOutMsg), which can be implemented inside my main
application to retrieve the incoming data?
Like how many serial comm components work where they buffer internally
all incoming data and fire an OnRxData event when there is new data to
read for the parent application....

If so, how would one go about adding this functionality to the object?

For reference here is the unit code in the old post by midiman, but
hopefully better formatted for readability:
{code}
unit ChildProc;

interface

uses
Windows, SysUtils, StrUtils;

resourcestring sSetStdHandleMsg = 'SetStdHandle(STD_INPUT_HANDLE, Value)';
resourcestring sCreatePipeMsg = 'Pipe.'+Chr(13)+Chr(13)+'CreatePipe(FChildStdoutRd , FChildStdoutWr, saAttr, 0)';
resourcestring sDuplicateHandleMsg = 'DuplicateHandle(GetCurrentProcess(), FChildStdoutRd, GetCurrentProcess(), @FChildStdoutRdDup, 0, False, DUPLICATE_SAME_ACCESS)';
resourcestring sCreateChildProcessMsg = 'CreateChildProcess(ExeName, CommadLine, FChildStdoutWr)';


type

  ESetStdHandleErr = class(Exception);
  ECreatePipeErr = class(Exception);
  EDuplicateHandleErr = class(Exception);
  ECreateChildProcessErr = class(Exception);

  { THandledObject }

  { This is a generic class for all encapsulated WinAPI's which need to call
  CloseHandle when no longer needed. This code eliminates the need for
  3 identical destructors in the TEvent, TMutex, and TSharedMem classes
  which are descended from this class. }

  THandledObject = class(TObject)
  protected
    FHandle: THandle;
  public
    destructor Destroy; override;
    property Handle: THandle read FHandle;
  end;

  { TMutex }

  { This class encapsulates the concept of a Win32 mutex. See "CreateMutex"
  in the Win32 reference for more information }

  TMutex = class(THandledObject)
  public
    constructor Create(const Name: string);
    function Get(TimeOut: Integer): Boolean;
    function Release: Boolean;
  end;

  { TChildProc }
  TChildProc = class(TObject)
    FStdIn: THandle;
    FStdOut: THandle;
    FsaAttr: PSecurityAttributes;
    FChildStdoutRd: THandle;
    FChildStdoutWr: THandle;
    FChildStdinRd: THandle;
    FChildStdinWr: THandle;
    piProcInfo: TProcessInformation;
  private
    function CreateChildProcess(ExeName, CommadLine: String; StdIn: THandle; StdOut: THandle; ShowWindow: word): Boolean;
  public
    constructor Create(ExeName, CommadLine: String; ShowWindow: word);
    destructor Destroy; override;
    function ReadStrFromChild(Timeout: Integer=1000): String;
    function WriteToChild(Data: String; Timeout: Integer=1000): Boolean;
    function Running: boolean;
  end;

implementation

{ THandledObject }

destructor THandledObject.Destroy;
begin
  if FHandle <> 0 then
  CloseHandle(FHandle);
end;

{ TMutex }

constructor TMutex.Create(const Name: string);
begin
  FHandle := CreateMutex(nil, False, PChar(Name));
  if FHandle = 0 then abort;
end;

function TMutex.Get(TimeOut: Integer): Boolean;
begin
  Result := WaitForSingleObject(FHandle, TimeOut) = WAIT_OBJECT_0;
end;

function TMutex.Release: Boolean;
begin
  Result := ReleaseMutex(FHandle);
end;

{ TChildProc }

constructor TChildProc.Create(ExeName, CommadLine: String; ShowWindow: word);
Var
  Tmp1, Tmp2: THandle;
begin
  New(FsaAttr);
  Try
  FsaAttr.nLength:=SizeOf(SECURITY_ATTRIBUTES);
  FsaAttr.bInheritHandle:=True;
  FsaAttr.lpSecurityDescriptor:=Nil;
  If not CreatePipe(FChildStdoutRd, FChildStdoutWr, FsaAttr, 0) Then
    raise ECreatePipeErr.CreateRes(@sCreatePipeMsg)
  Else
    If not CreatePipe(FChildStdinRd, FChildStdinWr, FsaAttr, 0) Then
      raise ECreatePipeErr.CreateRes(@sCreatePipeMsg)
    Else
    begin
      If not DuplicateHandle(GetCurrentProcess(), FChildStdoutRd, GetCurrentProcess(), @Tmp1, 0, False, DUPLICATE_SAME_ACCESS) Then
        raise EDuplicateHandleErr.CreateRes(@sDuplicateHandleMsg )
      Else
        If not DuplicateHandle(GetCurrentProcess(), FChildStdinWr, GetCurrentProcess(), @Tmp2, 0, False, DUPLICATE_SAME_ACCESS) Then
          raise EDuplicateHandleErr.CreateRes(@sDuplicateHandleMsg )
        Else
        begin
          CloseHandle(FChildStdoutRd);
          CloseHandle(FChildStdinWr);
          FChildStdoutRd:=Tmp1;
          FChildStdinWr:=Tmp2;
          If not CreateChildProcess(ExeName, CommadLine, FChildStdinRd, FChildStdoutWr, ShowWindow ) Then
          raise ECreateChildProcessErr.CreateRes(@sCreateChildProcessMsg)
        end;
    end;
  Finally
    Dispose(FsaAttr);
  End;
end;

function TChildProc.CreateChildProcess(ExeName, CommadLine: String; StdIn, StdOut: THandle; ShowWindow: word): Boolean;
Var
  siStartInfo: TStartupInfo;
begin
  // Set up members of STARTUPINFO structure.
  ZeroMemory(@siStartInfo, SizeOf(TStartupInfo));
  siStartInfo.cb := SizeOf(TStartupInfo);
  siStartInfo.hStdInput := StdIn;
  siStartInfo.hStdOutput := StdOut;
  siStartInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  siStartInfo.wShowWindow := ShowWindow;
  // Create the child process.
  Result := CreateProcess(Nil,
                          PChar(ExeName + ' ' + CommadLine), // command line
                          Nil, // process security attributes
                          Nil, // primary thread security attributes
                          TRUE, // handles are inherited
                          0, // creation flags
                          Nil, // use parent's environment
                          Nil, // use parent's current directory
                          siStartInfo, // STARTUPINFO pointer
                          piProcInfo); // receives PROCESS_INFORMATION
end;

destructor TChildProc.Destroy;
begin
  CloseHandle(FChildStdoutRd);
  CloseHandle(FChildStdoutWr);
  CloseHandle(FChildStdinRd);
  CloseHandle(FChildStdinWr);
end;

function TChildProc.ReadStrFromChild(Timeout: Integer): String;
Var
  i: Integer;
  dwRead, BufSize, DesBufSize: DWORD;
  chBuf: PChar;
  Res: Boolean;
begin
  Try
    BufSize:=0;
    New(chBuf);
    Repeat
      For i:=0 to 9 do
      begin
        Res:=PeekNamedPipe(FChildStdoutRd, nil, 0, nil, @DesBufSize, nil);
        Res:=Res and (DesBufSize > 0);
        If Res Then
          Break;
        Sleep(Round(Timeout/10));
      end;
      If Res Then
      begin
        If DesBufSize > BufSize Then
        begin
          FreeMem(chBuf);
          GetMem(chBuf, DesBufSize);
          BufSize:=DesBufSize;
        end;
        Res:=ReadFile(FChildStdoutRd, chBuf^, BufSize, dwRead, Nil);
        Result:=Result+LeftStr(chBuf, dwRead);
      end;
    Until not Res;
  Except
    Result:='Read Err';
  End;
end;


function TChildProc.Running: boolean;
var
  tmpHandle: THandle;
begin
  tmpHandle := OpenProcess( PROCESS_QUERY_INFORMATION, false, piProcInfo.dwProcessId );

  if tmpHandle > 0 then
  begin
    Result := true;
    CloseHandle( tmpHandle );
  end
  else
    Result := false;
end;

function TChildProc.WriteToChild(Data: String; Timeout: Integer=1000): Boolean;
Var
  dwWritten, BufSize: DWORD;
  chBuf: PChar;
begin
  chBuf:=PChar(Data+Chr($0D)+Chr($0A));
  BufSize:=Length(chBuf);
  Result:=WriteFile(FChildStdinWr, chBuf^, BufSize, dwWritten, Nil);
  Result:=Result and (BufSize = dwWritten);
end;

end.
{code}

--

Bo Berglund
Developer in Sweden

Edited by: Bo Berglund on Aug 30, 2012 9:38 AM
(Had to change the code formatting tag to make it readable)
0
Bo
8/30/2012 7:41:02 AM
Reply:

Similar Artilces:

Disadvantage in running an ASP.NET 32-bit application on a 64-bit Windows server in 32-bit mode?
 Hello,My ASP.NET application has some 32-bit DLLs I can't change.  I've deployed the application to a 64-bit Windows 2003 server and I can get it to run if I enable 32-bit ASP.NET support.My question:  is this configuration worth it?  Or would I be better off just running it on a Windows 32-bit Server?  Even more specifically, can a 32-bit application running on 64-bit Windows take advantage of the extra RAM the machine might have?Thanks!Mike There's really no disadvantage in running 32 bit application pool on a 64 bits system.With 64 bits OS, the OS ...

Occasional errors with 32-bit Delphi 7 application on Windows 7 64-bit
Hi, I have a 32-bit Delphi 7 application which was deployed on some machines with Windows 7 64-bit. The application occasionally displays errors such as: "Error reading ppDBText37.Border.Color: Invalid property value" or "Error reading Label24.Font.Ch: Property Ch does not exist" (here the name "Charset" was apparently truncated to "Ch") I checked how those properties are declared on the form where the errors occurred, and all seems ok: - First form (where "Error reading ppDBText37.Border.Color: Invalid property value" occurs): ...

Excel 64-bit and Delphi 32-bit
Hi, Any known issues with using Excel 2010 64-bit with a Delphi 32-bit app (Delphi 2009) My app uses the ExcelXP TExcelApplication object and nothing real fancy. I basically opens Excel, gets a list of all the ranges, and then updates the cells. It works fine with Excel 2007 but I have one customer who is reporting problems and he has Excel 2010 64-bit. Also, is there a way for my app to determine if Excel is 32 or 64-bit so that I can log an appropriate message. -- Bob Small I think one the main points of the new Delphi 64-bit compiler was that it was required to be able...

Running 32 Bit Apps under 64 Bit install
Newbie to Suse 9 Enterprise server. I am in the process of installing Suse 9 on our server which supports 64 bits. I was told that the application that we want to run has not been complied for 64 bit nor tested yet. My question is has anyone seen any problems running 32 bit apps under 64 bit mod? Is there any documentation on this? Thanks jjwansch@ingr.com wrote: > Newbie to Suse 9 Enterprise server. > I am in the process of installing Suse 9 on our server which supports 64 > bits. I was told that the application that we want to run has not been > complie...

running 32-bit application with 64-bit engine
We have a 32-bit application which is built with MSVC 2005 and running in Windows environment. Without recompile the application to 64-bit, can I use Sybase SQL Anywhere 64-bit engine to communicate with this application to access data from database? Mei, Yes, a 32-bit client can successfully connect to a 64-bit server. If you have any problems, you should post back here with the details. Regards, Mei wrote: > We have a 32-bit application which is built with MSVC 2005 > and running in Windows environment. Without recompile the > application to 64-bit, can I use Syb...

XML for Delphi XE6 32-bit/64-bit
I am looking for a straight-forward no frills XML library or component that allows me to easily form an XML file and to parse it easily as a means to transfer text (could be long and lengthy) information back and forth between applications. I would appreciate any recommendation of such a resource. Or maybe XML is not a good option for my application? Thanking you all in advance. Andy Andy wrote: > I am looking for a straight-forward no frills XML library or component > that allows me to easily form an XML file and to parse it easily as a > means to transfer text (co...

Running a 32 bit application in 64 bit openSUSE possible?
I am owner of (a very costly) STATA 32 bit license. I tried to run it on a 64 bit openSUSE but currently it does not even start. Question: is it possible to run a 32 bit native application in 64 bit openSUSE? (Under 32 bit it runs very well). Question 2: if possible, what kind of sources do I have to install in order to guarantee compatibility (and that might not be installed by default). System: opensuse 11.1 with KDE 3.5. Software STATA 8.0. Sorry if somewhere someone should have written something about that issue. I tried a search but the keywords would be so generic th...

Is delphi xe4 IDE 32 bit application?
Hi, I am trying to install a BPL compiled with win64 platform into DELPHI XE4 IDE. It is throwing an error "it is not a valid win32 application". is it means that DELPHI XE4 IDE is 32 bit application? if so , is it available in WIN64 too? thanks sudheer "Sudheer Bondalapati" wrote in message news:615522@forums.embarcadero.com... > > I am trying to install a BPL compiled with win64 platform into DELPHI XE4 > IDE. It is throwing an error "it is not a valid win32 application". > > is it means that DELPHI XE4 IDE is 32 bit appl...

32 bit Delphi Active X Control on 64 Bit machines
I'm using BDS 2006 and created a very simple Active X control ( COM ) ocx file that does nothing but return a string in a property. Placing the control on a .net application that contains a label reflecting the property builds and runs beautifully in 32 bit Windows Vista. Moving the application to Windows 7 64 bit fails. Debugging shows it doesn't even get to initialization. Is it possible to use COM through syswow64? <Steven Davis> wrote in message news:225825@forums.embarcadero.com... > I'm using BDS 2006 and created a very simple Active X control > ( COM ) ...

Probable Stupid Question: Using 64-bit Code on 64-bit Processors running 32-bit Windows...
Hi, Does anyone know if it is possible to do 64-bit processing (probably by writing some assembly language code) when running on a 64-bit CPU under 32-bit Windows? As near as I can tell, one has to develop all 64-bit code on a 64-bit machine running 64-bit windows and the target machines for 64-bit code have to be 64-bit machines running 64-bit windows. What might be useful, if it is possible, would be being able to detect a 64-bit processor when running 32-bit windows and take advantage of that to speed up some calculations. DanH ...

Migration from 32 bit application to 64 bit application
 Hi,I already have existing asp.net site which is running on 32 bit box with 2.0 framework and sql 2005. Can i migrate this application to 64 bit box  with 3.0 framework? What are the benefits i would get in this migration? would there be any performance gains in terms of speed? What kind of issues i can expect to have in this migrationthanksPrady  Not sure if you are going to gain any benefit out of it. It would be a minor performance enhancement (due to 64bit) that might not be visible to users' eyes..NET 3.0/Sql Server 2005 are fully compatible w/ 64 bit, so you won&#...

Run 32-bit app from 16-bit app
We want to run Excel 97 (32-bit) from a PB app (16-bit PB5.0.2). We cannot get Excel 97 to run from a 16-bit PB app with the "Run(Excel.exe)" function. How can we get it to work? Is it any work-around, outside software or middle ware to enable us to do this? TIA, Soo ...

Run 32 bit app from 16 bit app
We want to run Excel 97 (32-bit) from a PB app (16-bit PB5.0.2). We cannot get Excel 97 to run from a 16-bit PB app with the "Run(Excel.exe)" function. How can we get it to work? Is it any work-around, outside software or middle ware to enable us to do this? TIA, Soo You can try using an excel OLE control and calling the ole_control.Activate(OFFSITE!) command to activate excel. Be careful though I have had difficulty using a 16-bit pb app making ole calls on a 23-bit OS like Win95 - it seems to cause big gpf's. Soo Lam wrote: > We want to run Excel 97 (...

Probable Stupid Question: Using 64-bit Code on 64-bit Processors running 32-bit Windows... #2
Hi, Does anyone know if it is possible to do 64-bit processing (probably by writing some assembly language code) when running on a 64-bit CPU under 32-bit Windows? As near as I can tell, one has to develop all 64-bit code on a 64-bit machine running 64-bit windows and the target machines for 64-bit code have to be 64-bit machines running 64-bit windows. What might be useful, if it is possible, would be being able to detect a 64-bit processor when running 32-bit windows and take advantage of that to speed up some calculations. DanH Dan Hale wrote: > Does anyone k...

Web resources about - Running 64 bit console application from a 32 bit Delphi GUI app? - embarcadero.delphi.ide

Application - Wikipedia, the free encyclopedia
Text is available under the Creative Commons Attribution-ShareAlike License ;additional terms may apply. By using this site, you agree to the ...

Intriguing patent application describes how Apple might supercharge both Touch ID and trackpads
An intriguing Apple patent application published today describes how the Touch ID home button could gain additional functionality, allowing it ...

Stugan Games Accelerator Opens Applications for 2016
Games accelerator Stugan has opened its application process for its 2016 summer program. The program will accept 20 aspiring game developers, ...

eHosting DataFort to provide next generation data centre services with its Cisco Application-Centric ...
Al-Bawaba eHosting DataFort to provide next generation data centre services with its Cisco Application-Centric Infrastructure ... Al-Bawaba ...

Remote application server streamlines Windows desktop delivery
... that they need is therefore a challenging task. Cross platform solutions specialist Parallels is launching a new version of its Remote Application ...

Tech City UK received just 37 applications for a visa route that allows 200
Tech City UK, a taxpayer-funded government organisation, has received just 37 applications since April 2015 for a dedicated technology visa that ...

Toshiba Launches 40V N-ch Low ON-resistance Power MOSFET for Automotive Applications
Toshiba launched a 40V N-ch power MOSFET, &quot;TKR74F04PB,&quot; for automobile applications, including DC-DC converters, high capacity motor ...

MBA: Mortgage Applications Increased in Latest Weekly Survey, Purchase Applications up 22% YoY
From the MBA: Mortgage Applications Increase as Rates Continue to Drop in Latest MBA Weekly Survey Mortgage applications increased 8.8 percent ...

Mortgage applications drop 2.6%
Mortgage rates fell last week, but so did record amounts of snow across much of the East Coast. Here's the connection.

The USPTO updates their refusal of Sony's 'Let's Play' trademark application
... and Trademarks Office shot them down. What was interesting was the USPTO’s justification for doing so. They didn’t originally deny the application ...

Resources last updated: 2/8/2016 10:13:11 PM