Subversion Repositories aysalia

Rev

Rev 24 | Rev 27 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 24 Rev 26
1
program AyDos;
1
program AyDos;
2
 
2
 
3
// Aysalia DOS Launcher
3
// Aysalia DOS Launcher
4
// Revision 2018-12-07
4
// Revision 2018-12-07
5
// (C) 2018 Daniel Marschall, ViaThinkSoft
5
// (C) 2018 Daniel Marschall, ViaThinkSoft
6
 
6
 
7
// This launcher does launch DOSBox with the correct *.conf file,
7
// This launcher does launch DOSBox with the correct *.conf file,
8
// centers the window and changes the window title and icon at runtime.
8
// centers the window and changes the window title and icon at runtime.
9
 
9
 
10
uses
10
uses
11
  SysUtils,
11
  SysUtils,
12
  ShellAPI,
12
  ShellAPI,
13
  Windows,
13
  Windows,
14
  Messages;
14
  Messages;
15
 
15
 
16
{$R *.RES}
16
{$R *.RES}
17
 
17
 
18
const
18
const
19
  DOSBOX_EXE = 'DOSBox.exe';
19
  DOSBOX_EXE = 'DOSBox.exe';
20
 
20
 
21
var
21
var
22
  hPsApiDll: Cardinal = 0;
22
  hPsApiDll: Cardinal = 0;
23
  hIcon: THandle = 0;
23
  hIcon: THandle = 0;
24
  bCeneredOnce: boolean = false;
24
  bCeneredOnce: boolean = false;
25
 
25
 
26
(*
26
(*
27
function GetModuleFileNameEx(inProcess: THandle; inModule: THandle;
27
function GetModuleFileNameEx(inProcess: THandle; inModule: THandle;
28
      Filename: PChar; size: DWord): DWord; stdcall;
28
      Filename: PChar; size: DWord): DWord; stdcall;
29
      external 'psapi.dll' name 'GetModuleFileNameExA';
29
      external 'psapi.dll' name 'GetModuleFileNameExA';
30
*)
30
*)
31
{$IFDEF UNICODE}
31
{$IFDEF UNICODE}
32
function GetModuleFileNameEx(inProcess: THandle; inModule: THandle; Filename: PWideChar; size: DWord): Integer;
32
function GetModuleFileNameEx(inProcess: THandle; inModule: THandle; Filename: PWideChar; size: DWord): Integer;
33
type
33
type
34
  TGetModuleFileNameExFunc = function (inProcess: THandle; inModule: THandle; Filename: PWideChar; size: DWord): DWord; stdcall;
34
  TGetModuleFileNameExFunc = function (inProcess: THandle; inModule: THandle; Filename: PWideChar; size: DWord): DWord; stdcall;
35
var
35
var
36
  funcGetModuleFileNameEx: TGetModuleFileNameExFunc;
36
  funcGetModuleFileNameEx: TGetModuleFileNameExFunc;
37
begin
37
begin
38
  if hPsApiDll <> 0 then
38
  if hPsApiDll <> 0 then
39
  begin
39
  begin
40
    @funcGetModuleFileNameEx := GetProcAddress(hPsApiDll, 'GetModuleFileNameExW');
40
    @funcGetModuleFileNameEx := GetProcAddress(hPsApiDll, 'GetModuleFileNameExW');
41
    if Assigned(funcGetModuleFileNameEx) then
41
    if Assigned(funcGetModuleFileNameEx) then
42
      result := funcGetModuleFileNameEx(inProcess, inModule, Filename, size)
42
      result := funcGetModuleFileNameEx(inProcess, inModule, Filename, size)
43
    else
43
    else
44
      result := -1;
44
      result := -1;
45
  end
45
  end
46
  else result := -2;
46
  else result := -2;
47
end;
47
end;
48
{$ELSE}
48
{$ELSE}
49
function GetModuleFileNameEx(inProcess: THandle; inModule: THandle; Filename: PAnsiChar; size: DWord): Integer;
49
function GetModuleFileNameEx(inProcess: THandle; inModule: THandle; Filename: PAnsiChar; size: DWord): Integer;
50
type
50
type
51
  TGetModuleFileNameExFunc = function (inProcess: THandle; inModule: THandle; Filename: PAnsiChar; size: DWord): DWord; stdcall;
51
  TGetModuleFileNameExFunc = function (inProcess: THandle; inModule: THandle; Filename: PAnsiChar; size: DWord): DWord; stdcall;
52
var
52
var
53
  funcGetModuleFileNameEx: TGetModuleFileNameExFunc;
53
  funcGetModuleFileNameEx: TGetModuleFileNameExFunc;
54
begin
54
begin
55
  if hPsApiDll <> 0 then
55
  if hPsApiDll <> 0 then
56
  begin
56
  begin
57
    @funcGetModuleFileNameEx := GetProcAddress(hPsApiDll, 'GetModuleFileNameExA');
57
    @funcGetModuleFileNameEx := GetProcAddress(hPsApiDll, 'GetModuleFileNameExA');
58
    if Assigned(funcGetModuleFileNameEx) then
58
    if Assigned(funcGetModuleFileNameEx) then
59
      result := funcGetModuleFileNameEx(inProcess, inModule, Filename, size)
59
      result := funcGetModuleFileNameEx(inProcess, inModule, Filename, size)
60
    else
60
    else
61
      result := -1;
61
      result := -1;
62
  end
62
  end
63
  else result := -2;
63
  else result := -2;
64
end;
64
end;
65
{$ENDIF}
65
{$ENDIF}
66
 
66
 
67
procedure ChangeTitleAndIcon(hWnd: Thandle);
67
procedure ChangeTitleAndIcon(hWnd: Thandle);
68
var
68
var
69
  Title: array[0..255] of Char;
69
  Title: array[0..255] of Char;
70
const
70
const
71
  TargetWinWidth = 640;
71
  TargetWinWidth = 640;
72
  TargetWinHeight = 480;
72
  TargetWinHeight = 480;
73
resourcestring
73
resourcestring
74
  AyDosTitle = 'Aysalia DOS';
74
  AyDosTitle = 'Aysalia DOS';
75
  AyDos1Title = 'Aysalia DOS I';
75
  AyDos1Title = 'Aysalia DOS 1';
76
  AyDos2Title = 'Aysalia DOS II';
76
  AyDos2Title = 'Aysalia DOS 2';
77
begin
77
begin
78
  ZeroMemory(@Title, sizeof(Title));
78
  ZeroMemory(@Title, sizeof(Title));
79
  GetWindowText(hWnd, @Title, sizeof(Title)-1);
79
  GetWindowText(hWnd, @Title, sizeof(Title)-1);
80
 
80
 
81
  // Center window (once)
81
  // Center window (once)
82
  if (Title = 'DOSBox') and not bCeneredOnce then
82
  if (Title = 'DOSBox') and not bCeneredOnce then
83
  begin
83
  begin
84
    MoveWindow(hWnd, GetSystemMetrics(SM_CXSCREEN) div 2 - TargetWinWidth div 2,
84
    MoveWindow(hWnd, GetSystemMetrics(SM_CXSCREEN) div 2 - TargetWinWidth div 2,
85
                     GetSystemMetrics(SM_CYSCREEN) div 2 - TargetWinHeight div 2,
85
                     GetSystemMetrics(SM_CYSCREEN) div 2 - TargetWinHeight div 2,
86
                     TargetWinWidth,
86
                     TargetWinWidth,
87
                     TargetWinHeight,
87
                     TargetWinHeight,
88
                     true);
88
                     true);
89
    bCeneredOnce := true;
89
    bCeneredOnce := true;
90
  end;
90
  end;
91
 
91
 
92
  // Change window title
92
  // Change window title
93
  if Pos('AYDOS1', Title) > 0 then
93
  if Pos('AYDOS1', Title) > 0 then
94
    SetWindowText(hWnd, PChar(AyDos1Title))
94
    SetWindowText(hWnd, PChar(AyDos1Title))
95
  else if Pos('AYDOS2', Title) > 0 then
95
  else if Pos('AYDOS2', Title) > 0 then
96
    SetWindowText(hWnd, PChar(AyDos2Title))
96
    SetWindowText(hWnd, PChar(AyDos2Title))
97
  else
97
  else if Pos('AYDOS', Title) > 0 then
98
    SetWindowText(hWnd, PChar(AyDosTitle));
98
    SetWindowText(hWnd, PChar(AyDosTitle));
99
 
99
 
100
  // Change window and taskbar icon
100
  // Change window and taskbar icon
101
  if hIcon > 0 then
101
  if hIcon > 0 then
102
  begin
102
  begin
103
    // Change both icons to the same icon handle.
103
    // Change both icons to the same icon handle.
104
    SendMessage(hWnd, WM_SETICON, ICON_SMALL, hIcon);
104
    SendMessage(hWnd, WM_SETICON, ICON_SMALL, hIcon);
105
    SendMessage(hWnd, WM_SETICON, ICON_BIG, hIcon);
105
    SendMessage(hWnd, WM_SETICON, ICON_BIG, hIcon);
106
 
106
 
107
    // This will ensure that the application icon gets changed too.
107
    // This will ensure that the application icon gets changed too.
108
    SendMessage(GetWindow(hWnd, GW_OWNER), WM_SETICON, ICON_SMALL, hIcon);
108
    SendMessage(GetWindow(hWnd, GW_OWNER), WM_SETICON, ICON_SMALL, hIcon);
109
    SendMessage(GetWindow(hWnd, GW_OWNER), WM_SETICON, ICON_BIG, hIcon);
109
    SendMessage(GetWindow(hWnd, GW_OWNER), WM_SETICON, ICON_BIG, hIcon);
110
  end;
110
  end;
111
end;
111
end;
112
 
112
 
113
function EnumWindowsProc(Handle: hWnd; dummy: DWORD): BOOL; stdcall;
113
function EnumWindowsProc(Handle: hWnd; dummy: DWORD): BOOL; stdcall;
114
var
114
var
115
  Title: array[0..255] of Char;
115
  Title: array[0..255] of Char;
116
  WinFileName: array[0..MAX_PATH] of Char;
116
  WinFileName: array[0..MAX_PATH] of Char;
117
var
117
var
118
  PID: DWORD;
118
  PID: DWORD;
119
  hProcess: THandle;
119
  hProcess: THandle;
120
  Len: Integer;
120
  Len: Integer;
121
begin
121
begin
122
  Result := True;
122
  Result := True;
123
  ZeroMemory(@WinFileName, sizeof(WinFileName));
123
  ZeroMemory(@WinFileName, sizeof(WinFileName));
124
  GetWindowThreadProcessId(Handle, @PID);
124
  GetWindowThreadProcessId(Handle, @PID);
125
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
125
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
126
  Len := GetModuleFileNameEx(hProcess, 0, WinFileName, sizeof(WinFileName)-1);
126
  Len := GetModuleFileNameEx(hProcess, 0, WinFileName, sizeof(WinFileName)-1);
127
  if Len > 0 then
127
  if Len > 0 then
128
  begin
128
  begin
129
    // GetModuleFileNameEx is available on newer operating systems;
129
    // GetModuleFileNameEx is available on newer operating systems;
130
    // it ensures that we find the correct window by checking its EXE filename.
130
    // it ensures that we find the correct window by checking its EXE filename.
131
    if SameText(WinFileName, ExtractFilePath(ParamStr(0)) + DOSBOX_EXE) then
131
    if SameText(WinFileName, ExtractFilePath(ParamStr(0)) + DOSBOX_EXE) then
132
    begin
132
    begin
133
      Result := False; // stop enumeration
133
      Result := False; // stop enumeration
134
      ChangeTitleAndIcon(Handle);
134
      ChangeTitleAndIcon(Handle);
135
    end;
135
    end;
136
  end
136
  end
137
  else if Len < 0 then
137
  else if Len < 0 then
138
  begin
138
  begin
139
    // At Win9x, there is no psapi.dll, so we try it the old fashioned way,
139
    // At Win9x, there is no psapi.dll, so we try it the old fashioned way,
140
    // finding the window by parts of its title
140
    // finding the window by parts of its title
141
    ZeroMemory(@Title, sizeof(Title));
141
    ZeroMemory(@Title, sizeof(Title));
142
    GetWindowText(Handle, Title, sizeof(Title)-1);
142
    GetWindowText(Handle, Title, sizeof(Title)-1);
143
    if IsWindowVisible(Handle) then
143
    if IsWindowVisible(Handle) then
144
    begin
144
    begin
145
      if (title = 'DOSBox') or ((Pos('DOSBox ',   title) > 0) and
145
      if (title = 'DOSBox') or ((Pos('DOSBox ',   title) > 0) and
146
                                (Pos('Cpu speed', title) > 0)) then
146
                                (Pos('Cpu speed', title) > 0)) then
147
      begin
147
      begin
148
        Result := False; // stop enumeration
148
        Result := False; // stop enumeration
149
        ChangeTitleAndIcon(Handle);
149
        ChangeTitleAndIcon(Handle);
150
      end;
150
      end;
151
    end;
151
    end;
152
  end;
152
  end;
153
end;
153
end;
154
 
154
 
155
function ShellExecuteWait(hWnd: HWND; Operation, FileName, Parameters,
155
function ShellExecuteWait(hWnd: HWND; Operation, FileName, Parameters,
156
  Directory: PChar; ShowCmd: Integer): DWord;
156
  Directory: PChar; ShowCmd: Integer): DWord;
157
var
157
var
158
  Info: TShellExecuteInfo;
158
  Info: TShellExecuteInfo;
159
  pInfo: PShellExecuteInfo;
159
  pInfo: PShellExecuteInfo;
160
begin
160
begin
161
  pInfo := @Info;
161
  pInfo := @Info;
162
  with Info do
162
  with Info do
163
  begin
163
  begin
164
    cbSize       := SizeOf(Info);
164
    cbSize       := SizeOf(Info);
165
    fMask        := SEE_MASK_NOCLOSEPROCESS;
165
    fMask        := SEE_MASK_NOCLOSEPROCESS;
166
    wnd          := hWnd;
166
    wnd          := hWnd;
167
    lpVerb       := Operation;
167
    lpVerb       := Operation;
168
    lpFile       := FileName;
168
    lpFile       := FileName;
169
    lpParameters := PChar(Parameters + #0);
169
    lpParameters := PChar(Parameters + #0);
170
    lpDirectory  := PChar(Directory);
170
    lpDirectory  := PChar(Directory);
171
    nShow        := ShowCmd;
171
    nShow        := ShowCmd;
172
    hInstApp     := 0;
172
    hInstApp     := 0;
173
  end;
173
  end;
174
  ShellExecuteEx(pInfo);
174
  ShellExecuteEx(pInfo);
175
 
175
 
176
  repeat
176
  repeat
177
    result := WaitForSingleObject(Info.hProcess, 10);
177
    result := WaitForSingleObject(Info.hProcess, 10);
178
    EnumWindows(@EnumWindowsProc, 0);
178
    EnumWindows(@EnumWindowsProc, 0);
179
  until (result <> WAIT_TIMEOUT);
179
  until (result <> WAIT_TIMEOUT);
180
end;
180
end;
181
 
181
 
182
function Main: Integer;
182
function Main: Integer;
183
var
183
var
184
  sFile: string;
184
  sFile: string;
185
begin
185
begin
186
  ShellExecuteWait(0, 'open', DOSBOX_EXE, '-noconsole -conf DOSBox.conf',
186
  ShellExecuteWait(0, 'open', DOSBOX_EXE, '-noconsole -conf DOSBox.conf',
187
    PChar(ExtractFilePath(ParamStr(0))), SW_NORMAL);
187
    PChar(ExtractFilePath(ParamStr(0))), SW_NORMAL);
188
 
188
 
189
  sFile := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))) + 'stdout.txt';
189
  sFile := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))) + 'stdout.txt';
190
  if FileExists(sFile) then DeleteFile(PChar(sFile));
190
  if FileExists(sFile) then DeleteFile(PChar(sFile));
191
 
191
 
192
  sFile := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))) + 'stderr.txt';
192
  sFile := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))) + 'stderr.txt';
193
  if FileExists(sFile) then DeleteFile(PChar(sFile));
193
  if FileExists(sFile) then DeleteFile(PChar(sFile));
194
 
194
 
195
  result := 0;
195
  result := 0;
196
end;
196
end;
197
 
197
 
198
begin
198
begin
199
  hPsApiDll := LoadLibrary('psapi.dll');
199
  hPsApiDll := LoadLibrary('psapi.dll');
200
  try
200
  try
201
    hIcon := LoadIcon(hInstance, 'MainIcon');
201
    hIcon := LoadIcon(hInstance, 'MainIcon');
202
    ExitCode := Main;
202
    ExitCode := Main;
203
  finally
203
  finally
204
    FreeLibrary(hPsApiDll);
204
    FreeLibrary(hPsApiDll);
205
    hPsApiDll := 0;
205
    hPsApiDll := 0;
206
  end;
206
  end;
207
end.
207
end.
208
 
208