2005. október 21., péntek
Edit *.pif files programmatically
Problem/Question/Abstract:
Does anybody know how to create and/ or modify a *.pif programmatically? Windows creates *.pif files for all DOS programs but does not provide any method to edit it except manually. Is that right?
Answer:
procedure CreateShortcut(const FileName: string; Location: ShortcutType);
{Procedure to create a shortcut on the desktop or startmenu}
var
MyObject: IUnknown;
MySLink: IShellLink;
MyPFile: IPersistFile;
Directory: string;
LinkName: string;
IconName: string;
DirName: string;
pifName: WideString;
WFileName: WideString;
QuickLaunchReg: TRegIniFile;
aPidl: PItemIDList;
Res: HResult;
Buf: PByteArray;
PPif: pif_record_ref_type absolute Buf;
Flag: boolean;
i, j: integer;
n: longint;
PHeading: section_heading_record_ref_type;
PVMMSection: windows_vmm_section_ref_type;
PW386Section: ^windows_386_section_type;
f: file;
begin
MyObject := CreateComObject(CLSID_ShellLink);
MySLink := MyObject as IShellLink;
MyPFile := MyObject as IPersistFile;
MySLink.SetPath(PChar(FileName));
LinkName := ChangeFileExt(FileName, '.lnk');
LinkName := ExtractFileName(LinkName);
case Location of
_DESKTOP:
Res := SHGetSpecialFolderLocation(Application.Handle, CSIDL_DESKTOPDIRECTORY,
aPidl);
_STARTMENU:
Res := SHGetSpecialFolderLocation(Application.Handle, CSIDL_STARTMENU, aPidl);
_SENDTO:
Res := SHGetSpecialFolderLocation(Application.Handle, CSIDL_SENDTO, aPidl);
_QUICKLAUNCH:
Res := 0;
end;
if Res <> NOERROR then
begin
case Location of
_DESKTOP:
Directory := 'ShellFolders->Desktop';
_STARTMENU:
Directory := 'ShellFolders->Start Menu';
_SENDTO:
Directory := 'ShellFolders->SendTo';
_QUICKLAUNCH:
Directory := 'MapGroups->Quick Launch';
end;
ShowMessage(Directory + ': Failed');
end
else
begin
{Get the actual path from the PItemIDList}
SetLength(Directory, MAX_PATH);
SHGetPathFromIDList(aPidl, PChar(Directory));
SetLength(Directory, StrLen(PChar(Directory)));
WFileName := Directory + '\' + LinkName;
if (Location = _DESKTOP) and (LinkName = 'PAULITA.lnk') then
begin
pifName := ExtractFilePath(FileName);
Res := MyPFile.Load(PWChar(pifName + 'SYS\PauLita.pif'), 0);
if Res = E_OUTOFMEMORY then
ShowMessage('.PIF LOAD: Out of Memory')
else if Res = E_FAIL then
ShowMessage('.PIF LOAD: Failed');
IconName := pifName + 'SYS\PAULITA.ICO';
Res := MySLink.SetIconLocation(PChar(IconName), 0);
if Res <> NOERROR then
ShowMessage('SetIconLocation: Failed');
end;
MySLink.SetPath(PChar(FileName));
DirName := ExtractFilePath(FileName);
DirName := Copy(DirName, 1, Length(DirName) - 1);
MySLink.SetWorkingDirectory(PChar(DirName));
Res := MyPFile.Save(PWChar(WFileName), FALSE);
if Res <> S_OK then
ShowMessage('Save ' + WFileName + ' Failed');
if (Location = _DESKTOP) and (LinkName = 'PAULITA.lnk') then
begin
Buf := nil;
Assign(f, Directory + '\PAULITA.PIF');
try
Reset(f, 1);
n := FileSize(f);
GetMem(Buf, n);
BlockRead(f, Buf^, n);
PW386Section := nil;
Flag := FALSE;
i := $187;
while i + SizeOf(section_heading_record_type) <= n do
begin
PHeading := @Buf^[i];
{ShowMessage(PHeading^.Name); }
{Look for WINDOWS 386 3.0 group}
if StrPas(@PHeading^.Name) = 'WINDOWS 386 3.0' then
begin
PW386Section := @Buf^[i + SizeOf(section_heading_record_type)];
end;
{Look for WINDOWS VMM 4.0 group}
if StrPas(@PHeading^.Name) = 'WINDOWS VMM 4.0' then
begin
Flag := TRUE;
Break;
end;
i := i + SizeOf(section_heading_record_type) + PHeading^.Len;
end;
if not Flag then
begin
ShowMessage('WINDOWS VMM 4.0 not Found in' + Directory + '\PAULITA.PIF');
end
else
begin
Flag := FALSE;
if (PPif^.Flags1 and CLOSE_ON_EXIT) = $0000 then
begin
PPif^.Flags1 := PPif^.Flags1 or CLOSE_ON_EXIT;
Flag := TRUE;
end;
j := Pos('PAULITA.EXE', PPif^.FileName);
if j > 0 then
begin
StrPCopy(PPif^.FileName, Copy(StrPas(@PPif^.FileName), 1, j - 1) +
'LITA.BAT'#0);
Flag := TRUE;
end;
if PW386Section <> nil then
begin
if (PW386Section^.Flags1 and $00000008) = $0000 then
begin
{Used}
PW386Section^.Flags1 := PW386Section^.Flags1or $00000008;
{Full screen mode}
Flag := TRUE;
end;
if (PW386Section^.MaxEMS <> $FFFF) or (PW386Section^.ReqEMS <> $0000) or
(PW386Section^.MaxXMS <> $FFFF) or (PW386Section^.ReqXMS <> $0000) then
begin
PW386Section^.MaxEMS := $FFFF;
PW386Section^.ReqEMS := $0000;
PW386Section^.MaxXMS := $FFFF;
PW386Section^.ReqXMS := $0000;
Flag := TRUE;
end;
end;
PVMMSection := @Buf^[i + SizeOf(section_heading_record_type)];
if (PVMMSection^.Flags2 and FULL_SCREEN_MODE) = $0000 then
begin
{Not used}
PVMMSection^.Flags2 := PVMMSection^.Flags2 or FULL_SCREEN_MODE;
Flag := TRUE;
end;
if Flag then
begin
Seek(f, 0);
BlockWrite(f, Buf^, n);
end;
end;
finally
Close(f);
if Buf <> nil then
FreeMem(Buf, n);
end;
end;
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése