Windows NT 4.0 source code leak
 
 
 
 
 
 

2224 lines
60 KiB

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
dllpmnt1.c
Abstract:
This module contains various calls needed internally for PM/NT
These calls implement the following API's:
(all API's deal with groups and programs)
WinCreateGroup
WinAddProgram
WinChangeProgram
WinQueryProgramTitles
WinQueryDefinition
WinDestroyGroup
WinRemoveProgram
PrfCreateGroup
PrfAddProgram
PrfChangeProgram
PrfQueryProgramTitles
PrfQueryDefinition
PrfQueryProgramHandle
PrfDestroyGroup
PrfRemoveProgram
Implementation:
PM makes profiling in order to manage groups and programs.
PMNT do not use a profile. Instead it connect PROGMAN (program manager)
in order to execute commands or request data.
The connection is done using the DDEML package:
where service=PROGMAN, topic=PROGMAN.
It is important to notice that when creaing or removing
programs, the respective group must be active, since there is
no parameter for the group.
OS2 uses handles, while NT uses groups' and programs' names.
An atom table implements the interface.
We couldn't use the Win32 API's of atoms because they lacked
the ability to rename an atom.
Author:
Lior Moshaiov (LiorM) 9-June-1993
Revision History:
Added Clipboard Module (LiorM) 10-Nov-1993
This module contains various calls needed internally for PM/NT
These calls implement the interface between PM & WIN32 clipboards:
(all API's deal with clipboard)
WinOpenClipbrd
WinEmptyClipbrd
WinCloseClipbrd
WinSetClipbrdData (text & bitmap)
WinQueryClipbrdData (text & bitmap)
WinQueryClipbrdFmtInfo (text & bitmap)
--*/
#if PMNT /* If not for PMNT build, yield just an empty file */
// We need here both Win32 & Os2ss include files.
// Since they interfere, the needed definitions of os2ss & pm
// were inserted by hand.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "ddeml.h"
#include "os2tile.h"
#include "os2nt.h"
#include "os2crt.h"
//The following definitions should be compatible with ntrtl.h
PVOID
NTAPI
RtlAllocateHeap(
IN PVOID HeapHandle,
IN ULONG Flags,
IN ULONG Size
);
BOOLEAN
NTAPI
RtlFreeHeap(
IN PVOID HeapHandle,
IN ULONG Flags,
IN PVOID BaseAddress
);
//The following definitions should be compatible with os2dll.h
#define CANONICALIZE_FILE_OR_DEV 0x00000001
typedef struct _STRING {
USHORT Length;
USHORT MaximumLength;
#ifdef MIDL_PASS
[size_is(MaximumLength), length_is(Length) ]
#endif // MIDL_PASS
PCHAR Buffer;
} STRING;
typedef STRING *PSTRING;
#define APIRET ULONG
APIRET
Od2Canonicalize(
IN PSZ Path,
IN ULONG ExpectedType,
OUT PSTRING OutputString,
OUT PHANDLE OutputDirectory OPTIONAL,
OUT PULONG ParseFlags OPTIONAL,
OUT PULONG FileType OPTIONAL
);
VOID
Od2ProbeForWrite(
IN PVOID Address,
IN ULONG Length,
IN ULONG Alignment
);
typedef unsigned short SEL;
typedef SEL *PSEL;
#define APIRET ULONG
typedef HANDLE HSEM, *PHSEM;
APIRET
DosFreeSeg(
SEL Sel);
APIRET
DosAllocSeg(
IN USHORT cbSize,
OUT PSEL pSel,
IN USHORT fsAlloc);
APIRET
DosAllocHuge(
IN ULONG cSegs,
IN USHORT cbPartialSeg,
OUT PSEL pSel,
IN ULONG cMaxSegs,
IN USHORT fsAlloc
);
APIRET
DosSemClear(
IN HSEM hsem
);
APIRET
DosSemSet(
IN HSEM hsem
);
APIRET
DosSemWait(
IN HSEM hsem,
IN LONG lTimeOut
);
#pragma pack (1)
//The following definitions should be compatible with
// pmnt\tiger\src\h\pmwin.h
typedef struct _SWP { /* swp */
USHORT fs;
SHORT cy;
SHORT cx;
SHORT y;
SHORT x;
HWND hwndInsertBehind;
HWND hwnd;
} SWP;
typedef SWP FAR *PSWP;
#define CFI_SELECTOR 0x0100
#define CFI_HANDLE 0x0200
//The following definitions should be compatible with
// pmnt\tiger\src\h\pmshl.h
#define MAXNAMEL 60
/* window size structure */
typedef struct _XYWINSIZE { /* xywin */
SHORT x;
SHORT y;
SHORT cx;
SHORT cy;
USHORT fsWindow;
} XYWINSIZE;
typedef XYWINSIZE FAR *PXYWINSIZE;
/* Definitions for fsWindow */
#define XYF_NOAUTOCLOSE 0x0008
#define XYF_MINIMIZED 0x0004 /* D23914 */
#define XYF_MAXIMIZED 0x0002 /* D23914 */
#define XYF_INVISIBLE 0x0001
#define XYF_NORMAL 0X0000
/* program handle */
typedef void far *LHANDLE; /* hprog */
typedef LHANDLE HPROGRAM; /* hprog */
/* maximum path length */
#define MAXPATHL 128
/* root group handle */
#define SGH_ROOT (HPROGRAM) -1L
typedef struct _HPROGARRAY { /* hpga */
HPROGRAM ahprog[1];
} HPROGARRAY;
typedef HPROGARRAY FAR *PHPROGARRAY;
typedef CHAR PROGCATEGORY; /* progc */
typedef PROGCATEGORY FAR *PPROGCATEGORY;
/* values acceptable for PROGCATEGORY for PM groups */
#define PROG_DEFAULT (PROGCATEGORY)0
#define PROG_FULLSCREEN (PROGCATEGORY)1
#define PROG_WINDOWABLEVIO (PROGCATEGORY)2
#define PROG_PM (PROGCATEGORY)3
#define PROG_GROUP (PROGCATEGORY)5
#define PROG_REAL (PROGCATEGORY)4 /* was 7 */
#define PROG_DLL (PROGCATEGORY)6
#define PROG_RESERVED (PROGCATEGORY)255
/* visibility flag for PROGTYPE structure */
#define SHE_VISIBLE (BYTE)0x00
#define SHE_INVISIBLE (BYTE)0x01
#define SHE_RESERVED (BYTE)0xFF
typedef struct _PROGTYPE { /* progt */
PROGCATEGORY progc;
UCHAR fbVisible;
} PROGTYPE;
typedef PROGTYPE FAR *PPROGTYPE;
#pragma pack (1)
typedef struct _PROGRAMENTRY { /* proge */
HPROGRAM hprog;
PROGTYPE progt;
CHAR szTitle[MAXNAMEL+1];
} PROGRAMENTRY;
typedef PROGRAMENTRY FAR *PPROGRAMENTRY;
typedef struct _PIBSTRUCT { /* pib */
PROGTYPE progt;
CHAR szTitle[MAXNAMEL+1];
CHAR szIconFileName[MAXPATHL+1];
CHAR szExecutable[MAXPATHL+1];
CHAR szStartupDir[MAXPATHL+1];
XYWINSIZE xywinInitial;
USHORT res1;
LHANDLE res2;
USHORT cchEnvironmentVars;
PCH pchEnvironmentVars;
USHORT cchProgramParameter;
PCH pchProgramParameter;
} PIBSTRUCT;
typedef PIBSTRUCT FAR *PPIBSTRUCT;
/******************************************************************************/
/* */
/* Structures associated with 'Prf' calls */
/* */
/******************************************************************************/
typedef struct _PROGDETAILS { /* progde */
ULONG Length; /* set this to sizeof(PROGDETAILS) */
PROGTYPE progt;
USHORT pad1[3]; /* ready for 32-bit PROGTYPE */
PSZ pszTitle; /* any of the pointers can be NULL */
PSZ pszExecutable;
PSZ pszParameters;
PSZ pszStartupDir;
PSZ pszIcon;
PSZ pszEnvironment; /* this is terminated by /0/0 */
SWP swpInitial; /* this replaces XYWINSIZE */
USHORT pad2[5]; /* ready for 32-bit SWP */
} PROGDETAILS;
typedef PROGDETAILS FAR *PPROGDETAILS;
typedef struct _PROGTITLE { /* progti */
HPROGRAM hprog;
PROGTYPE progt;
USHORT pad1[3]; /* padding ready for 32-bit PROGTYPE */
PSZ pszTitle;
} PROGTITLE;
typedef PROGTITLE FAR *PPROGTITLE;
#pragma pack ()
extern PVOID Od2Heap;
#define MAXNAME (MAXNAMEL+1)
// Atoms: There are atom tables of 256 entries each.
// the 1st entry points to the next table.
// all tables are allocated dynamically when needed.
// each handle (32 bits) consists of 2 atoms(16 bits):
// the most significant is the group atom (0 for the desktop),
// and the least is the atom of the program.
// the most significant byte of each atom is the table no. (1->255)
// the least significant is the index in the table (1->255)
//
#define PMNT_TABLE_POWER 8
#define PMNT_ATOMS_IN_TABLE (2<<(PMNT_TABLE_POWER-1))
#define PMNT_HANDLE_TO_ATOM(a) ((a) & 0x0000ffff)
#define PMNT_TABLE_OF_ATOM(a) (USHORT)(((a)>>PMNT_TABLE_POWER) & 0x000000ff)
#define PMNT_INDEX_OF_ATOM(a) (USHORT)((a) & 0x000000ff)
#define PMNT_INDEX_TO_ATOM(a,b) ((((a)<<PMNT_TABLE_POWER)|b) & 0x0000ffff)
#define PMNT_ATOM_TO_HANDLE(a,b) (ULONG) (((a)<<(2*PMNT_TABLE_POWER)) | ((b) & 0x0000ffff))
static USHORT pmnt_no_of_atom_tables = 0;
static USHORT pmnt_atoms_in_last_table = 0;
static char **pmnt_1st_atom_table=NULL;
static char **pmnt_last_atom_table=NULL;
PCHAR
PMNTGetAtomEntry(ULONG hprog)
{
USHORT table_no,index,i;
ULONG atom;
char **table;
atom = PMNT_HANDLE_TO_ATOM(hprog);
table_no = PMNT_TABLE_OF_ATOM (atom);
index= PMNT_INDEX_OF_ATOM (atom);
if (table_no > pmnt_no_of_atom_tables)
return(NULL);
if (table_no == pmnt_no_of_atom_tables && index > pmnt_atoms_in_last_table)
return(NULL);
if (!(table = pmnt_1st_atom_table))
return(NULL);
for (i=1;i<table_no;i++) {
if (!(table = (char **) table[0]))
return(NULL);
}
return (table[index]);
}
ULONG
PMNTGetAtomName(ULONG hprog, char *szName, ULONG maxsize)
{
ULONG len;
char *ptr_src,*ptr_dst;
if (!(ptr_src = PMNTGetAtomEntry(hprog))) {
return(0L);
}
ptr_dst = szName;
len=0;
while((len<maxsize)&&(*ptr_dst++ = *ptr_src++)) len++;
return(len);
}
BOOL
PMNTRenameAtom(ULONG hprog, char *szNewName)
{
char *ptr_src,*ptr_dst;
if (!(ptr_dst = PMNTGetAtomEntry(hprog))) {
return(FALSE);
}
RtlFreeHeap(Od2Heap, 0, ptr_dst);
ptr_dst = RtlAllocateHeap(Od2Heap, 0, (int) (strlen(szNewName)+1));
ptr_src = szNewName;
while(*ptr_dst++ = *ptr_src++);
return(TRUE);
}
ULONG
PMNTExistAtom(char *szName)
{
char **table;
USHORT i,j,no_entries;
if (!pmnt_no_of_atom_tables) {
return(0L);
}
if (!(table = pmnt_1st_atom_table))
return(0L);
no_entries = PMNT_ATOMS_IN_TABLE-1;
for (i=1;i<=pmnt_no_of_atom_tables;i++) {
if (i == pmnt_no_of_atom_tables)
no_entries = pmnt_atoms_in_last_table;
for(j=1;j<=no_entries;j++) {
if (!strncmp (szName,table[j],MAXNAME)) {
return(PMNT_INDEX_TO_ATOM(i,j));
}
}
if (i<pmnt_no_of_atom_tables) {
if (!(table = (char **) table[0]))
return(0L);
}
}
return(0L);
}
ULONG
PMNTAddAtom(ULONG hParent,char *szName)
{
char *buf;
ULONG atom;
char **table;
if (!(atom = PMNTExistAtom(szName))) {
//should be added
if (!pmnt_atoms_in_last_table ||
(pmnt_atoms_in_last_table == PMNT_ATOMS_IN_TABLE-1)) {
// a new table should be created
if(!(table =
RtlAllocateHeap(Od2Heap, 0, PMNT_ATOMS_IN_TABLE *sizeof(char *)))){
return(0L);
}
if (pmnt_no_of_atom_tables == 0) {
pmnt_last_atom_table = pmnt_1st_atom_table = table;
}
else {
pmnt_last_atom_table[0] = (void *) table;
pmnt_last_atom_table = table;
}
pmnt_no_of_atom_tables++;
pmnt_atoms_in_last_table = 0;
}
pmnt_atoms_in_last_table++;
if (! (pmnt_last_atom_table[pmnt_atoms_in_last_table]=buf=
RtlAllocateHeap(Od2Heap, 0, (int) (strlen(szName)+1)))){
return(0L);
}
strcpy(buf,szName);
atom = PMNT_INDEX_TO_ATOM(pmnt_no_of_atom_tables,pmnt_atoms_in_last_table);
}
return(PMNT_ATOM_TO_HANDLE(hParent,atom));
}
// These functions retrieve strings from text in CF_TEXT format.
// The format is :
// each line ends with a CR & LF (0x0d, 0x0a)
// the thex ends with the NULL char ('\0')
// 1. information about progman:
// each line consists of group name.
// 2. information about a group
// 1st line contains information about the group
// All the other lines contain information about programs in the group
// (a line for each program)
// "proram_name","command",startup_directory,icon_path,xPosition,yPosition,icon_index,Hotkey,Minimize
//
BOOL
PMNTGetNextStart(
PCHAR *ptr_src)
{
char *p1,*p2,*p3;
p1 = strchr (*ptr_src,(int)0x0d);
p2 = strchr (*ptr_src,',');
if (p2 && p2<p1) {
*ptr_src = ++p2;
p2 = strchr (*ptr_src,',');
p3 = strchr (*ptr_src,'"');
if (p3 && p3<p1 && ( !p2 || p3<p2)) {
*ptr_src = ++p3;
return(TRUE);
}
}
return(FALSE);
}
ULONG
PMNTGetThisString(
PCHAR *ptr_src, char *buffer, ULONG maxbuf)
{
char *ptr_Cf_Text,*ptr_buf;
ULONG i = 0;
ptr_Cf_Text = *ptr_src;
if (maxbuf) {
ptr_buf = buffer;
while((i<maxbuf) && (*ptr_buf++ = *ptr_Cf_Text++) != '"') i++;
*--ptr_buf = '\0';
}
else {
while(*ptr_Cf_Text++ != '"') i++;
}
*ptr_src = ptr_Cf_Text;
return(i);
}
ULONG
PMNTGetThisString1(
PCHAR *ptr_src, char *buffer, ULONG maxbuf, ULONG *param)
{
char *ptr_Cf_Text,*ptr_buf;
ULONG i = 0;
ptr_Cf_Text = *ptr_src;
if (maxbuf) {
ptr_buf = buffer;
while((i<maxbuf) && (*ptr_buf = *ptr_Cf_Text) != '"' && (*ptr_buf != ' ')) {
i++;
ptr_buf++;
ptr_Cf_Text++;
}
*ptr_buf = '\0';
}
else {
while(*ptr_Cf_Text != '"' && *ptr_Cf_Text != ' ') {
ptr_Cf_Text++;
i++;
}
}
if (*param = (*ptr_Cf_Text++ == ' '))
while (*ptr_Cf_Text == ' ') *ptr_Cf_Text++;
*ptr_src = ptr_Cf_Text;
return(i);
}
ULONG
PMNTGetNextString(
PCHAR *ptr_src, char *buffer, ULONG maxbuf)
{
if (!PMNTGetNextStart(ptr_src)) {
return(0L);
}
return(PMNTGetThisString(ptr_src,buffer,maxbuf));
}
ULONG
PMNTGetNextString1(
PCHAR *ptr_src, char *buffer, ULONG maxbuf, ULONG *param)
{
if (!PMNTGetNextStart(ptr_src)) {
return(0L);
}
return(PMNTGetThisString1(ptr_src,buffer,maxbuf,param));
}
ULONG
PMNTGetNextString0(
PCHAR *ptr_src, char *buffer, ULONG maxbuf)
{
char *ptr_Cf_Text,*ptr_buf;
ULONG i=0;
char *p1,*p2;
ptr_Cf_Text = *ptr_src;
p1 = strchr (ptr_Cf_Text,(int)0x0d);
p2 = strchr (ptr_Cf_Text,',');
if (p2 && p2<p1)
ptr_Cf_Text = ++p2;
else
return(0L);
if (maxbuf) {
ptr_buf = buffer;
while((i<maxbuf) && (*ptr_buf++ = *ptr_Cf_Text++) != ',') i++;
*--ptr_buf = '\0';
}
else {
while(*ptr_Cf_Text++ != ',') i++;
}
*ptr_src = ptr_Cf_Text;
return(i);
}
#define MYMAXBUF 512
// retrieves canonicalized name of file from file name & starting directory
ULONG
PMNTGetFullPath(
char *file_name, char *st_dir, PSTRING canonic_name)
{
LPCSTR *ptr;
ULONG len=0,FileFlags,FileType;
char buf[MYMAXBUF],path_name[MYMAXBUF];
short change_dir;
if (change_dir = (st_dir && *st_dir)) {
GetCurrentDirectory((DWORD)MYMAXBUF,(LPSTR)buf);
SetCurrentDirectory((LPSTR) st_dir);
}
do {
len = (ULONG)
SearchPath((LPCSTR) NULL,(LPCSTR) file_name, (LPCSTR) ".EXE", (DWORD) MYMAXBUF,
(LPSTR) path_name, (LPSTR *) &ptr);
if (!len || len > MYMAXBUF) {
KdPrint(("PMNTGetFullPath : SearchPath failed\n"));
len = 0;
break;
}
if (Od2Canonicalize(path_name,CANONICALIZE_FILE_OR_DEV,canonic_name,NULL,
&FileFlags,&FileType)) {
len = 0;
break;
}
} while (FALSE);
if (change_dir) {
SetCurrentDirectory((LPSTR) buf);
}
return(len);
}
// The following functions are a layer between the API's and DDEML
// They are called after a connection with progman has been settled
// and they get strings (instead of handles) as input
// This layer is needed since some API's call the same DdeClientTransaction
#define DDE_TIME_OUT 120000L // 2 minutes timeout
BOOL
PMNTCreateGrp (
HCONV hConv, char *GroupName)
{
char buffer[256];
HDDEDATA rc;
strcpy (buffer,"[CreateGroup(");
strcat (buffer,GroupName);
strcat (buffer,",0)]");
rc = DdeClientTransaction((LPBYTE)buffer,strlen(buffer)+1,hConv,0L,0,
XTYP_EXECUTE,DDE_TIME_OUT,NULL);
if (!rc) {
KdPrint(("PMNTCreateGrp : transaction failed\n"));
return(FALSE);
}
DdeFreeDataHandle(rc);
return(TRUE);
}
BOOL
PMNTAddItem(
HCONV hConv,PCHAR szTitle,PCHAR szExecutable,PCHAR szStartupDir,PCHAR szParameters)
{
char buffer[256];
HDDEDATA rc;
char *ptr;
strcpy (buffer,"[AddItem(");
strcat (buffer,szExecutable);
if (szParameters && *szParameters) {
ptr = buffer + strlen(buffer);
*ptr++ = ' ';
strcpy(ptr,szParameters);
}
strcat (buffer,",");
strcat (buffer,szTitle);
strcat (buffer,",,,,,");
if (szStartupDir) {
strcat (buffer,szStartupDir);
}
strcat (buffer,")]");
rc = DdeClientTransaction((LPBYTE)buffer,strlen(buffer)+1,hConv,0L,0,
XTYP_EXECUTE,DDE_TIME_OUT,NULL);
if (!rc) {
KdPrint(("PMNTAddItem: transaction failed\n"));
return(FALSE);
}
DdeFreeDataHandle(rc);
return(TRUE);
}
BOOL
PMNTDeleteItem (
HCONV hConv, ULONG del_rep, char *szName)
{
char buffer[256];
HDDEDATA rc;
if (del_rep == 0)
strcpy (buffer,"[DeleteItem(");
else
strcpy (buffer,"[ReplaceItem(");
strcat (buffer,szName);
strcat (buffer,")]");
rc = DdeClientTransaction((LPBYTE)buffer,strlen(buffer)+1,hConv,0L,0,
XTYP_EXECUTE,DDE_TIME_OUT,NULL);
if (!rc) {
KdPrint(("PMNTDeleteItem: transaction failed\n"));
return(FALSE);
}
DdeFreeDataHandle(rc);
return(TRUE);
}
BOOL
PMNTGetGrpText(
DWORD idInst, HCONV hConv, char *szName, HDDEDATA *phData, PCHAR *ptr_Cf_Text)
{
DWORD cbData;
HSZ hszItem;
hszItem = DdeCreateStringHandle(idInst,szName,0);
*phData = DdeClientTransaction((LPBYTE)NULL,0,hConv,hszItem,CF_TEXT,
XTYP_REQUEST,DDE_TIME_OUT,NULL);
DdeFreeStringHandle(idInst,hszItem);
if (!(*phData)) {
KdPrint(("PMNTGetGrpText: transaction failed\n"));
return(FALSE);
}
if (!(*ptr_Cf_Text=DdeAccessData(*phData,&cbData))) {
KdPrint(("PMNTGetGrpText: access data failed\n"));
DdeFreeDataHandle(*phData);
return(FALSE);
}
return(TRUE);
}
BOOL
PMNTGetGroupText(
DWORD idInst, HCONV hConv, LONG hGroup, HDDEDATA *phData, PCHAR *ptr_Cf_Text)
{
char szGroupName[MAXNAME];
if (hGroup == (LONG) SGH_ROOT) {
strcpy(szGroupName,"PROGMAN");
}
else
if (!(PMNTGetAtomName(hGroup,szGroupName,MAXNAME))) {
KdPrint(("PMNTGetGroupText: PMNTGetAtomName failed\n"));
return(FALSE);
}
if (!PMNTGetGrpText(idInst,hConv,szGroupName,phData,ptr_Cf_Text)) {
return(FALSE);
}
return(TRUE);
}
ULONG
PMNTChangePrg(
DWORD idInst, HCONV hConv, char *szGroup, char *szOldProg,
char *szNewProg,char *szExecutable,char *szStartupDir,char *szParameters)
{
char *buffer,*ptr_c,*ptr_buf,*ptr_Cf_Text,szBuf[MAXNAME];
HDDEDATA hData,rc;
ULONG len;
short sucsess=FALSE;
short rtl_alloc=FALSE;
do {
if (!PMNTGetGrpText(idInst,hConv,szGroup,&hData,&ptr_Cf_Text)) {
return(FALSE);
}
if (!ptr_Cf_Text || !(*ptr_Cf_Text)) {
break;
}
// activate group
if (!PMNTCreateGrp(hConv,szGroup)) {
break;
}
// each line ends with CR LF,
// format is "name","command",startup dir,iconPath,xPos,yPos,iconindex,hotkey,minimize0x0d 0x0a
// 1st line consist the group name
// The order of parameters in AddItem is different
// "command","name",iconPath,iconIndex,xPos,yPos,startup dir,hotkey,minimize
while(*ptr_Cf_Text++ != 0x0a); //1st line
while (*ptr_Cf_Text) {
while (*ptr_Cf_Text++ != '"');
PMNTGetThisString(&ptr_Cf_Text,szBuf,MAXNAME);
if (!strncmp (szBuf,szOldProg,MAXNAME)) {
len = 10;
len+=strlen(szNewProg)+3;
len+=strlen(szExecutable)+3;
if (szParameters)
len+=strlen(szParameters)+1;
if (szStartupDir) {
len+=strlen(szStartupDir)+1;
}
else {
len++;
}
while (*ptr_Cf_Text++ != ',');
while (*ptr_Cf_Text++ != ',');
while (*ptr_Cf_Text++ != ',');
ptr_c = ptr_Cf_Text;
while (*ptr_c++ != 0x0d) len++;
len+=3;
buffer = RtlAllocateHeap(Od2Heap, 0, len);
rtl_alloc = TRUE;
strcpy(buffer,"[AddItem(");
strcat (buffer,szExecutable);
if (szParameters && *szParameters) {
ptr_buf = buffer + strlen(buffer);
*ptr_buf++ = ' ';
strcpy(ptr_buf,szParameters);
}
strcat (buffer,",");
strcat (buffer,szNewProg);
strcat (buffer,",");
ptr_buf = buffer + strlen(buffer);
// keep IconPath
while((*ptr_buf++ = *ptr_Cf_Text++) != ',');
// keep Icon Index
ptr_c = ptr_Cf_Text;
while(*ptr_c++ != ',');
while(*ptr_c++ != ',');
while((*ptr_buf++ = *ptr_c++) != ',');
// keep xPos,yPos
while((*ptr_buf++ = *ptr_Cf_Text++) != ',');
while((*ptr_buf++ = *ptr_Cf_Text++) != ',');
if (szStartupDir) {
strcpy(ptr_buf,szStartupDir);
}
ptr_buf += strlen(ptr_buf);
*ptr_buf++ = ',';
// keep HotKey, Minimize
ptr_Cf_Text = ptr_c;
while((*ptr_buf++ = *ptr_Cf_Text++) != 0x0d);
ptr_buf--;
strcpy(ptr_buf,")]");
if (!(PMNTDeleteItem(hConv,1L,szOldProg))) {
break;
}
//Add an Item
if (!(rc = DdeClientTransaction((LPBYTE)buffer,strlen(buffer)+1,hConv,0L,0,
XTYP_EXECUTE,DDE_TIME_OUT,NULL))) {
KdPrint(("PMNTChangePrg :transaction failed\n"));
break;
}
DdeFreeDataHandle(rc);
sucsess = TRUE;
break;
}
while (*ptr_Cf_Text++ != 0x0a);
}
} while (FALSE);
if (rtl_alloc) RtlFreeHeap(Od2Heap, 0, buffer);
DdeFreeDataHandle(hData);
return(sucsess);
}
BOOL
PMNTChangeGrp(
DWORD idInst, HCONV hConv, char *szOldGroup, char *szNewGroup)
{
char *buffer,*ptr_c,*ptr_buf,*ptr_Cf_Text,*ptr_xp;
HDDEDATA hData,rc;
ULONG len,maxbuf;
short sucsess=FALSE;
short rtl_alloc = FALSE;
do {
if (!PMNTGetGrpText(idInst,hConv,szOldGroup,&hData,&ptr_Cf_Text)) {
return(FALSE);
}
if (!ptr_Cf_Text || !(*ptr_Cf_Text)) {
break;
}
// create new group
if (!PMNTCreateGrp(hConv,szNewGroup)) {
break;
}
while(*ptr_Cf_Text++ != 0x0a); //1st line
ptr_c = ptr_Cf_Text;
maxbuf = 0;
while (*ptr_c) {
len = 0;
while (*ptr_c++ != 0x0a) len++;
if (len>maxbuf) maxbuf=len;
}
maxbuf+=12;
buffer = RtlAllocateHeap(Od2Heap, 0, maxbuf);
rtl_alloc= TRUE;
strcpy(buffer,"[AddItem(");
while (*ptr_Cf_Text) {
ptr_c = ptr_Cf_Text;
ptr_buf = buffer+9;
//copy cmd (2nd item)
while (*ptr_c++ != ',');
while ((*ptr_buf++ = *ptr_c++) != ',');
//copy name (1st item)
while ((*ptr_buf++ = *ptr_Cf_Text++) != ',');
ptr_Cf_Text = ptr_c; //both on end of 2nd item
//copy IconPath (4th item)
while (*ptr_c++ != ',');
while ((*ptr_buf++ = *ptr_c++) != ',');
ptr_xp = ptr_c; //start of xPosition
//copy IconIndex (7th item)
while (*ptr_c++ != ',');
while (*ptr_c++ != ',');
while ((*ptr_buf++ = *ptr_c++) != ',');
//copy xy position
while ((*ptr_buf++ = *ptr_xp++) != ',');
while ((*ptr_buf++ = *ptr_xp++) != ',');
//copy start directory
while ((*ptr_buf++ = *ptr_Cf_Text++) != ',');
//copy HotKey
while ((*ptr_buf++ = *ptr_c++) != ',');
//copy Minimize flag
while ((*ptr_buf++ = *ptr_c++) != 0x0d);
--ptr_buf;
ptr_Cf_Text = ptr_c;
while(*ptr_Cf_Text++ != 0x0a); //1st line
strcpy(ptr_buf,")]");
//Add an Item
if (!(rc = DdeClientTransaction((LPBYTE)buffer,strlen(buffer)+1,hConv,0L,0,
XTYP_EXECUTE,DDE_TIME_OUT,NULL))) {
KdPrint(("PMNTChangeGrp :transaction of add item failed\n"));
break;
}
DdeFreeDataHandle(rc);
ptr_Cf_Text = ptr_c;
while (*ptr_Cf_Text++ != 0x0a);
}
strcpy (buffer,"[DeleteGroup(");
strcat (buffer,szOldGroup);
strcat (buffer,",0)]");
if (!(rc = DdeClientTransaction((LPBYTE)buffer,strlen(buffer)+1,hConv,0L,0,
XTYP_EXECUTE,DDE_TIME_OUT,NULL))) {
KdPrint(("PMNTChangeGrp :transaction of delete group failed\n"));
break;
}
sucsess = TRUE;
DdeFreeDataHandle(rc);
} while (FALSE);
if (rtl_alloc) RtlFreeHeap(Od2Heap, 0, buffer);
DdeFreeDataHandle(hData);
return(sucsess);
}
ULONG
PMNTWinQueryProgramTitles (
char *ptr_Cf_Text, LONG hGroup, PPROGRAMENTRY paproge, ULONG cbBuf, PULONG pcTitles)
{
PPROGRAMENTRY ptr_proge;
char *ptr_Title;
ULONG entries;
USHORT i;
entries = cbBuf / sizeof(PPROGRAMENTRY);
if (!entries) {
// request only the no. of programs
while(*ptr_Cf_Text)
if (*ptr_Cf_Text++ == 0x0a) (*pcTitles)++;
if (hGroup != (LONG) SGH_ROOT) (*pcTitles)--;
}
else if (hGroup == (LONG) SGH_ROOT) {
// each line ends with CR LF, and consists of a group name
while(*pcTitles<entries) {
if (!(*ptr_Cf_Text)) break;
ptr_proge = &paproge[*pcTitles];
ptr_Title = ptr_proge->szTitle;
i=0;
while((i++<MAXNAME) && (*ptr_Title++ = *ptr_Cf_Text++) != 0x0d);
*--ptr_Title = '\0';
ptr_proge->hprog=
(HPROGRAM)PMNTAddAtom(0L,ptr_proge->szTitle);
ptr_proge->progt.progc=PROG_GROUP;
ptr_proge->progt.fbVisible=SHE_VISIBLE;
(*pcTitles)++;
ptr_Cf_Text++;
}
}
else {
// each line ends with CR LF,
// a program name in " " is in the beginning of each line
// followed by other parameters
// 1st line consist the group name
if (*ptr_Cf_Text) {
while(*ptr_Cf_Text++ != 0x0a); //1st line
while(*pcTitles<entries) {
if (!(*ptr_Cf_Text)) break;
ptr_proge = &paproge[*pcTitles];
ptr_Title = ptr_proge->szTitle;
while(*ptr_Cf_Text++ != '"');
i=0;
while((i++<MAXNAME) && ((*ptr_Title++=*ptr_Cf_Text++) != '"'));
*--ptr_Title = '\0';
ptr_proge->hprog=
(HPROGRAM)PMNTAddAtom((ULONG)hGroup,ptr_proge->szTitle);
ptr_proge->progt.progc=PROG_DEFAULT;
ptr_proge->progt.fbVisible=SHE_VISIBLE;
(*pcTitles)++;
while(*ptr_Cf_Text++ != 0x0a);
}
}
}
return(1L);
}
ULONG
PMNTPrfQueryProgramTitles (
char *start_Cf_Text, LONG hGroup, PPROGTITLE paprogti, ULONG cbBuf, PULONG pcTitles)
{
PPROGTITLE ptr_progti;
char *ptr_Title;
ULONG Length,i,uTitles;
char *ptr_Cf_Text,*st_Title;
*pcTitles=0;
Length=i=0;
ptr_Cf_Text = start_Cf_Text;
//calculate no. of items, and needed length
if (hGroup== (LONG) SGH_ROOT) {
// each line ends with CR LF,
while (*ptr_Cf_Text) {
while(*ptr_Cf_Text++ != 0x0d) i++;
(*pcTitles)++;
ptr_Cf_Text++;
}
}
else {
// each line ends with CR LF,
// a program name in " " is in the beginning of each line
// followed by other parameters
// 1st line consist the group name
if (*ptr_Cf_Text) {
while(*ptr_Cf_Text++ != 0x0a); //1st line
while (*ptr_Cf_Text) {
while(*ptr_Cf_Text++ != '"');
while(*ptr_Cf_Text++ != '"') i++;
(*pcTitles)++;
while(*ptr_Cf_Text++ != 0x0a);
}
}
}
Length = ((ULONG)(sizeof(PROGTITLE)+1) * (*pcTitles)) + i;
if (cbBuf) {
//the contents should be copied
if (Length > cbBuf) {
return(0L);
}
ptr_Title = (char *) &paprogti[*pcTitles];
ptr_Cf_Text = start_Cf_Text;
uTitles= 0;
if (hGroup == (LONG) SGH_ROOT) {
// each line ends with CR LF, and consists of a group name
while (*ptr_Cf_Text) {
st_Title = ptr_Title;
ptr_progti = &paprogti[uTitles++];
ptr_progti->pszTitle = (void *) FLATTOFARPTR(st_Title);
while((*ptr_Title++ = *ptr_Cf_Text++) != 0x0d);
*(ptr_Title-1) = '\0';
ptr_progti->hprog=
(HPROGRAM)PMNTAddAtom(0L,st_Title);
ptr_progti->progt.progc=PROG_GROUP;
ptr_progti->progt.fbVisible=SHE_VISIBLE;
ptr_Cf_Text++;
}
}
else {
// each line ends with CR LF,
// a program name in " " is in the beginning of each line
// followed by other parameters
// 1st line consist the group name
if (*ptr_Cf_Text) {
while(*ptr_Cf_Text++ != 0x0a); //1st line
while (*ptr_Cf_Text) {
st_Title = ptr_Title;
ptr_progti = &paprogti[uTitles++];
ptr_progti->pszTitle = (void *) FLATTOFARPTR(st_Title);
while(*ptr_Cf_Text++ != '"');
while((*ptr_Title++=*ptr_Cf_Text++) != '"');
*(ptr_Title-1) = '\0';
ptr_progti->hprog=
(HPROGRAM)PMNTAddAtom((ULONG)hGroup,st_Title);
ptr_progti->progt.progc=PROG_DEFAULT;
ptr_progti->progt.fbVisible=SHE_VISIBLE;
while(*ptr_Cf_Text++ != 0x0a);
}
}
}
}
return(Length);
}
ULONG
PMNTWinQueryDefinition (
char *ptr_Cf_Text, char *szName, PPIBSTRUCT ppib, ULONG cbBuf)
{
char szBuf[MAXNAME],*ptr_buf,*ptr_par;
ULONG Length = sizeof(PIBSTRUCT),len,maxbuf,param;
if (cbBuf) {
memset((char *)ppib,(int) 0,cbBuf);
ppib->progt.fbVisible=SHE_VISIBLE;
ppib->progt.progc= (ptr_Cf_Text) ? PROG_DEFAULT : PROG_GROUP;
strcpy(ppib->szTitle,szName);
}
if (ptr_Cf_Text) {
//if it is a program (and not a group)we should query other parameters
// each line ends with CR LF,
// format is "name","command",startup dir,iconPath,xPos,yPos,iconindex,hotkey,minimize0x0d 0x0a
// 1st line consist the group name
while(*ptr_Cf_Text++ != 0x0a); //1st line
while (*ptr_Cf_Text) {
while (*ptr_Cf_Text++ != '"');
PMNTGetThisString(&ptr_Cf_Text,szBuf,MAXNAME);
if (!strncmp (szBuf,szName,MAXNAME)) {
if (cbBuf) {
ptr_buf = ppib->szExecutable;
maxbuf = MAXPATHL+1;
ptr_par = (char *)ppib+Length;
ppib->pchProgramParameter = (void *) FLATTOFARPTR(ptr_par);
}
else {
ptr_buf = NULL;
maxbuf = 0;
}
Length++;
len = PMNTGetNextString1(&ptr_Cf_Text,ptr_buf,maxbuf,&param);
if (cbBuf) ptr_buf = ptr_par;
if (len && param) {
len = PMNTGetThisString(&ptr_Cf_Text,ptr_buf,maxbuf);
}
else
len = 0;
if (cbBuf) ppib->cchProgramParameter = (USHORT)(len+1);
Length += len;
if (cbBuf) {
PMNTGetNextString0(&ptr_Cf_Text,ppib->szStartupDir,maxbuf);
}
break;
}
}
}
return(Length+2);
}
ULONG
PMNTPrfQueryDefinition (
char *ptr_Cf_Text, char *szName, PPROGDETAILS pprogde, ULONG cbBuf)
{
char szBuf[MAXNAME],*ptr_st,*ptr_buf;
ULONG Length = sizeof(PROGDETAILS),len,maxbuf,param;
if (cbBuf) {
ptr_st = (char *) pprogde;
memset(ptr_st,(int) 0,cbBuf);
pprogde->Length = Length;
pprogde->progt.fbVisible=SHE_VISIBLE;
pprogde->progt.progc= (ptr_Cf_Text) ? PROG_DEFAULT : PROG_GROUP;
ptr_buf = ptr_st + Length;
pprogde->pszTitle= (void *) FLATTOFARPTR (ptr_buf);
strcpy(ptr_buf,szName);
}
Length += strlen(szName)+1;
if (ptr_Cf_Text) {
//if it is a program (and not a group)we should query other parameters
// each line ends with CR LF,
// format is "name","command",startup dir,iconPath,xPos,yPos,iconindex,hotkey,minimize0x0d 0x0a
// 1st line consist the group name
while(*ptr_Cf_Text++ != 0x0a); //1st line
while (*ptr_Cf_Text) {
while (*ptr_Cf_Text++ != '"');
PMNTGetThisString(&ptr_Cf_Text,szBuf,MAXNAME);
if (!strncmp (szBuf,szName,MAXNAME)) {
if (cbBuf) {
ptr_buf = ptr_st+Length;
pprogde->pszExecutable = (void *) FLATTOFARPTR(ptr_buf);
maxbuf = MAXPATHL+1;
}
else {
ptr_buf = NULL;
maxbuf = 0;
}
len = PMNTGetNextString1(&ptr_Cf_Text,ptr_buf,maxbuf,&param);
Length+= len+1;
if (cbBuf) {
ptr_buf = ptr_st+Length;
pprogde->pszParameters= (void *) FLATTOFARPTR(ptr_buf);
}
if (len && param) {
len = PMNTGetThisString(&ptr_Cf_Text,ptr_buf,maxbuf);
}
else
len = 0;
Length += len+1;
if (cbBuf) {
ptr_buf = ptr_st+Length;
pprogde->pszStartupDir= (void *) FLATTOFARPTR(ptr_buf);
}
len = PMNTGetNextString0(&ptr_Cf_Text,ptr_buf,maxbuf);
Length+=len+1;
if (cbBuf) {
ptr_buf = ptr_st+Length;
pprogde->pszIcon=(void *) FLATTOFARPTR(ptr_buf);
}
Length++;
break;
}
}
}
return(Length);
}
// This function establishes the connection with progman
BOOL
PMNTDdeConnect(
DWORD *pidInst, HCONV *phConv)
{
HSZ hszService,hszTopic;
*pidInst = 0L;
if (DdeInitialize (pidInst,NULL,
APPCLASS_STANDARD|APPCMD_CLIENTONLY, 0L)) {
KdPrint(("PMNTDdeConnect : DdeInitialize failed\n"));
return(FALSE);
}
hszService = DdeCreateStringHandle(*pidInst,"PROGMAN",0);
hszTopic = DdeCreateStringHandle(*pidInst,"PROGMAN",0);
*phConv = DdeConnect(*pidInst,hszService,hszTopic,NULL);
DdeFreeStringHandle(*pidInst,hszService);
DdeFreeStringHandle(*pidInst,hszTopic);
if (*phConv == (HCONV) 0) {
KdPrint(("PMNTDdeConnect : DdeConnect failed\n"));
DdeUninitialize(*pidInst);
return(FALSE);
}
return(TRUE);
}
// The following API's are exported API's that implement PM API's.
// The naming convention is: Win___, Prf___ are implemented by PMNT___
ULONG
PMNTCreateGroup(
PSZ GroupName, PULONG phGroup)
{
DWORD idInst;
BOOL sucsess;
HCONV hConv;
*phGroup = 0L;
sucsess = FALSE;
if (!GroupName || !(*GroupName)) {
return(0L);
}
do {
if (!PMNTDdeConnect(&idInst,&hConv)) {
return(0L);
}
if (!(PMNTCreateGrp(hConv,GroupName))) {
break;
}
sucsess = (BOOL) (*phGroup = PMNTAddAtom(0L,GroupName));
} while (FALSE);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
return(sucsess);
}
ULONG
PMNTQueryProgramTitles(
ULONG win_prf, LONG hGroup, PVOID ProgTitles, ULONG cbBuf, PULONG pcTitles)
{
DWORD idInst;
HCONV hConv;
HDDEDATA hData;
PCHAR ptr_Cf_Text;
ULONG Length;
*pcTitles=0;
Length=0;
do {
if (cbBuf) Od2ProbeForWrite(ProgTitles,1,1);
if (!PMNTDdeConnect(&idInst,&hConv)) {
return(0L);
}
if (!PMNTGetGroupText(idInst,hConv,hGroup,&hData,&ptr_Cf_Text)) {
break;
}
if (win_prf == 0L) {
Length = PMNTWinQueryProgramTitles(
ptr_Cf_Text,hGroup,ProgTitles,cbBuf,pcTitles);
}
else {
Length = PMNTPrfQueryProgramTitles(
ptr_Cf_Text,hGroup,ProgTitles,cbBuf,pcTitles);
}
DdeFreeDataHandle(hData);
} while (FALSE);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
return(Length);
}
ULONG
PMNTQueryDefinition(
ULONG win_prf, LONG hProg, PVOID ProgDefinition, ULONG cbBuf)
{
DWORD idInst;
HCONV hConv;
HDDEDATA hData;
PCHAR ptr_Cf_Text;
ULONG Length;
LONG hGroup;
char szName[MAXNAME];
Length=0;
hData = 0;
do {
if (cbBuf) Od2ProbeForWrite(ProgDefinition,1,1);
if (!PMNTDdeConnect(&idInst,&hConv)) {
return(0L);
}
if (!(PMNTGetAtomName(hProg,szName,MAXNAME))) {
KdPrint(("PMNTQueryDefinition : PMNTGetAtomName failed\n"));
break;
}
ptr_Cf_Text = NULL;
if (hGroup = (hProg>>16)) {
if (!PMNTGetGroupText(idInst,hConv,hGroup,&hData,&ptr_Cf_Text)) {
break;
}
}
if (win_prf == 0L) {
Length = PMNTWinQueryDefinition(
ptr_Cf_Text,szName,ProgDefinition,cbBuf);
}
else {
Length = PMNTPrfQueryDefinition(
ptr_Cf_Text,szName,ProgDefinition,cbBuf);
}
if (hData) DdeFreeDataHandle(hData);
} while (FALSE);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
return(Length);
}
ULONG
PMNTQueryProgramHandle(
PCHAR PathNameOS2, PHPROGARRAY phpga, ULONG cb, PULONG pcHandles)
{
DWORD idInst;
HCONV hConv;
HDDEDATA hDataG,hDataP;
ULONG Length;
ULONG len,entries,param,hGroup,hProg,i,FileFlags,FileType;
char GroupName[MYMAXBUF];
char ProgName[MYMAXBUF];
char FileNameNT[MYMAXBUF];
char StartDir[MYMAXBUF];
STRING CanonicNameNT,CanonicNameOS2;
char *ptr_Cf_Root,*ptr_Cf_Text,*ptr_grp;
*pcHandles=0;
Length=0;
entries = cb / sizeof(HPROGRAM);
do {
if (cb) Od2ProbeForWrite(phpga,1,1);
if (!PMNTDdeConnect(&idInst,&hConv)) {
return(0L);
}
if (!PMNTGetGroupText(idInst,hConv,(LONG)SGH_ROOT,&hDataG,&ptr_Cf_Root)) {
break;
}
while(*ptr_Cf_Root) {
// get group name
ptr_grp = GroupName;
i=0;
while((i++<MYMAXBUF) && ((*ptr_grp++ = *ptr_Cf_Root++) != 0x0d));
*--ptr_grp = '\0';
// get group programs
if (!PMNTGetGrpText(idInst,hConv,GroupName,&hDataP,&ptr_Cf_Text)) {
break;
}
while(*ptr_Cf_Text++ != 0x0a); // skip 1st line
while (*ptr_Cf_Text) {
while (*ptr_Cf_Text++ != '"');
PMNTGetThisString(&ptr_Cf_Text,ProgName,MYMAXBUF);
len = PMNTGetNextString1(&ptr_Cf_Text,FileNameNT,MYMAXBUF,&param);
if (len && param) {
PMNTGetThisString(&ptr_Cf_Text,NULL,0L);
}
PMNTGetNextString0(&ptr_Cf_Text,StartDir,MYMAXBUF);
while(*ptr_Cf_Text++ != 0x0a); // goto end of line of program
if (!PMNTGetFullPath(FileNameNT,StartDir,&CanonicNameNT)) {
break;
}
if (Od2Canonicalize(PathNameOS2,CANONICALIZE_FILE_OR_DEV
,&CanonicNameOS2,NULL,&FileFlags,&FileType)) {
RtlFreeHeap(Od2Heap, 0, CanonicNameNT.Buffer);
break;
}
strupr(CanonicNameNT.Buffer);
strupr(CanonicNameOS2.Buffer);
if (!strcmp(CanonicNameOS2.Buffer,CanonicNameNT.Buffer)) {
if (*pcHandles < entries) {
hGroup = PMNTAddAtom(0L,GroupName);
hProg = PMNTAddAtom(hGroup,ProgName);
phpga->ahprog[*pcHandles] = (HPROGRAM) hProg;
}
else if (cb) {
// buffer is not large enough
*pcHandles = 0L;
return(0L);
}
Length += sizeof(HPROGRAM);
(*pcHandles)++;
}
RtlFreeHeap(Od2Heap, 0, CanonicNameNT.Buffer);
RtlFreeHeap(Od2Heap, 0, CanonicNameOS2.Buffer);
}
DdeFreeDataHandle(hDataP); // free data of ptr_Cf_Text
while(*ptr_Cf_Root++ != 0x0a); // goto end of line of group
}
DdeFreeDataHandle(hDataG);
} while (FALSE);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
return(Length);
}
ULONG
PMNTAddProgram(
ULONG hGroupHandle,PCHAR szTitle,PCHAR szExecutable,PCHAR szStartupDir,
PCHAR szParameters, PULONG phProg)
{
DWORD idInst;
char szGroupName[MAXNAME];
short sucsess;
HCONV hConv;
*phProg = 0L;
sucsess = FALSE;
if (!(szTitle) || !(*szTitle)) {
return(0L);
}
if (!(szExecutable) || !(*szExecutable)) {
return(0L);
}
do {
if (!PMNTDdeConnect(&idInst,&hConv)) {
return(0L);
}
if (!(PMNTGetAtomName(hGroupHandle,szGroupName,MAXNAME))) {
break;
}
if (!(PMNTCreateGrp(hConv,szGroupName))) {
break;
}
if (!(PMNTAddItem(hConv,szTitle,szExecutable,szStartupDir,szParameters))) {
break;
}
sucsess = (BOOL) (*phProg = PMNTAddAtom(hGroupHandle,szTitle));
} while (FALSE);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
return(sucsess);
}
ULONG
PMNTChangeProgram(
ULONG hProg,PCHAR szTitle,PCHAR szExecutable,PCHAR szStartupDir,
PCHAR szParameters)
{
DWORD idInst;
char szParentName[MAXNAME];
char szName[MAXNAME];
short sucsess,changed_name;
ULONG hParent;
HCONV hConv;
HDDEDATA hData = 0;
sucsess = FALSE;
if (!(szTitle) || !(*szTitle)) {
return(0L);
}
if (hParent = (hProg>>16)) {
if (!(szExecutable) || !(*szExecutable)) {
return(0L);
}
}
do {
if (!PMNTDdeConnect(&idInst,&hConv)) {
return(0L);
}
if (!(PMNTGetAtomName(hProg,szName,MAXNAME))) {
break;
}
changed_name = strncmp(szName,szTitle,MAXNAME);
if (hParent) {
// should change a program item
// make its group active
PMNTGetAtomName(hParent,szParentName,MAXNAME);
if (!PMNTChangePrg(idInst,hConv,szParentName,szName
,szTitle,szExecutable,szStartupDir,szParameters)) {
break;
}
}
else {
// should change a group , the only thing we should care about is its name
if (changed_name) {
if (!PMNTChangeGrp(idInst,hConv,szName,szTitle)) {
break;
}
}
}
if (changed_name) {
PMNTRenameAtom(hProg,szTitle);
}
sucsess = TRUE;
} while (FALSE);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
return(sucsess);
}
BOOL
PMNTDestroyGroup(
LONG hGroupHandle)
{
DWORD idInst;
char buffer[256];
char szGroupName[MAXNAME];
short sucsess;
HCONV hConv;
HDDEDATA rc;
sucsess = FALSE;
do {
if (!PMNTDdeConnect(&idInst,&hConv)) {
return(FALSE);
}
PMNTGetAtomName(hGroupHandle,szGroupName,MAXNAME);
strcpy (buffer,"[DeleteGroup(");
strcat (buffer,szGroupName);
strcat (buffer,",0)]");
rc = DdeClientTransaction((LPBYTE)buffer,strlen(buffer)+1,hConv,0L,0,
XTYP_EXECUTE,DDE_TIME_OUT,NULL);
if (!rc) {
KdPrint(("PMNTDestroyGroup : transaction failed\n"));
break;
}
DdeFreeDataHandle(rc);
sucsess = TRUE;
} while (FALSE);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
return(sucsess);
}
BOOL
PMNTRemoveProgram(
LONG hProg)
{
DWORD idInst;
char szName[MAXNAME];
short sucsess;
HCONV hConv;
ULONG hGroup;
sucsess = FALSE;
do {
if (!PMNTDdeConnect(&idInst,&hConv)) {
return(FALSE);
}
hGroup = (hProg>>16);
PMNTGetAtomName(hGroup,szName,MAXNAME);
if (!(PMNTCreateGrp(hConv,szName))) {
break;
}
PMNTGetAtomName(hProg,szName,MAXNAME);
if (!(PMNTDeleteItem(hConv,0L,szName))) {
break;
}
sucsess = TRUE;
} while (FALSE);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
return(sucsess);
}
/*****************************************/
/* PM <-> WIN32 CLIPBOARD implementation */
/*****************************************/
#define PMNT_CF_TEXT 1
#define PMNT_CF_BITMAP 2
SEL QuerySel=0;
ULONG
PMNTOpenClipbrd(
IN HWND hwnd)
{
return((ULONG) OpenClipboard(hwnd));
}
ULONG
PMNTCloseClipbrd(
)
{
if (QuerySel)
{
DosFreeSeg(QuerySel);
QuerySel=0;
}
return((ULONG) CloseClipboard());
}
ULONG
PMNTEmptyClipbrd(
)
{
return ((ULONG) EmptyClipboard());
}
ULONG
PMNTSetClipbrdText(
IN ULONG ulData)
{
HANDLE handle;
char *ptrData,*ptrCopy;
DWORD cb;
SEL sel;
if (ulData) {
sel = (SEL) ulData;
ptrData = SELTOFLAT(sel);
cb = strlen(ptrData) + 1;
if (!(handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,cb))) {
return((ULONG) FALSE);
}
if (!(ptrCopy = GlobalLock(handle))) {
return((ULONG) FALSE);
}
while(*ptrCopy++=*ptrData++);
GlobalUnlock(handle);
}
else {
handle=NULL;
}
return ((SetClipboardData(CF_TEXT,handle)) ? (ULONG) TRUE : (ULONG) FALSE);
}
ULONG
PMNTSetClipbrdBitmap(
IN PBITMAPCOREINFO pbmiPM, IN PVOID lpbInit)
{
HBITMAP hbitmap;
HDC hdc;
USHORT no_of_colors,i;
PBITMAPINFO pbmi;
SEL selBitmapInfo;
USHORT cbBitmapInfo;
ULONG rc = FALSE;
if (! pbmiPM) {
return ((SetClipboardData(CF_BITMAP,NULL)) ? (ULONG) TRUE : (ULONG) FALSE);
}
no_of_colors = (pbmiPM->bmciHeader.bcBitCount <= 8)
? (1 << pbmiPM->bmciHeader.bcBitCount) : 0;
cbBitmapInfo = sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * (no_of_colors));
if (DosAllocSeg (cbBitmapInfo,&selBitmapInfo,0)) {
KdPrint(("PMNTSetClipbrdBitmap(): DosAllocSeg() failed\n"));
return(FALSE);
}
pbmi = SELTOFLAT(selBitmapInfo);
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = pbmiPM->bmciHeader.bcWidth;
pbmi->bmiHeader.biHeight = pbmiPM->bmciHeader.bcHeight;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = pbmiPM->bmciHeader.bcBitCount;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 0;
pbmi->bmiHeader.biXPelsPerMeter = 0;
pbmi->bmiHeader.biYPelsPerMeter = 0;
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biClrImportant = 0;
for (i=0;i<no_of_colors;i++) {
pbmi->bmiColors[i].rgbBlue = pbmiPM->bmciColors[i].rgbtBlue;
pbmi->bmiColors[i].rgbGreen = pbmiPM->bmciColors[i].rgbtGreen;
pbmi->bmiColors[i].rgbRed = pbmiPM->bmciColors[i].rgbtRed;
pbmi->bmiColors[i].rgbReserved = 0;
}
if (! (hdc = CreateDC("DISPLAY",NULL,NULL,NULL))) {
KdPrint(("PMNTSetClipbrdBitmap: CreateDC() faild\n"));
goto exit_set_bitmap_1;
}
if (! ( hbitmap = CreateDIBitmap(hdc,&(pbmi->bmiHeader),CBM_INIT,lpbInit,pbmi,DIB_RGB_COLORS))){
KdPrint(("PMNTSetClipbrdBitmap: CreateDIBitmap() faild\n"));
goto exit_set_bitmap_2;
}
rc = (SetClipboardData(CF_BITMAP,(HANDLE)hbitmap)) ? (ULONG) TRUE : (ULONG) FALSE;
exit_set_bitmap_2:
DeleteDC(hdc);
exit_set_bitmap_1:
DosFreeSeg(selBitmapInfo);
return(rc);
}
void
PMNTQueryClipbrdText(
OUT PULONG pulData)
{
HANDLE handle;
char *ptrData,*ptrCopy;
USHORT cb;
*pulData=0;
if (!(handle = GetClipboardData(CF_TEXT))) {
return;
}
if (!(ptrData = GlobalLock(handle))) {
return;
}
cb = strlen(ptrData) + 1;
if (QuerySel) {
DosFreeSeg(QuerySel);
}
if (DosAllocSeg(cb,&QuerySel,0)) {
KdPrint(("PMNTQueryClipbrdData: cannot allocate memory\n"));
return;
}
*pulData = (ULONG) QuerySel;
if (ptrCopy = SELTOFLAT(QuerySel)) {
while(*ptrCopy++=*ptrData++);
}
GlobalUnlock(handle);
}
ULONG
PMNTQueryClipbrdBitmap(
OUT PBITMAPCOREINFO *ppbmiPM, OUT PVOID *ppbBuffer)
{
HBITMAP hbitmap;
HDC hdc;
USHORT no_of_colors,i;
BITMAPINFO bmi;
PBITMAPINFO pbmi;
SEL selBitmapInfo,selBuffer;
USHORT cbBitmapInfo;
ULONG cbBuffer;
USHORT absHeight,absWidth;
ULONG rc = (ULONG)FALSE;
*ppbmiPM = NULL;
*ppbBuffer = NULL;
if (!(hbitmap = (HBITMAP) GetClipboardData(CF_BITMAP))) {
return((ULONG) FALSE);
}
if (! (hdc = CreateDC("DISPLAY",NULL,NULL,NULL))) {
KdPrint(("PMNTQueryClipbrdBitmap: CreateDC() faild\n"));
return((ULONG) FALSE);
}
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biBitCount = 0;
GetDIBits(hdc,hbitmap,0,0,NULL,&bmi,DIB_RGB_COLORS);
absHeight = abs(bmi.bmiHeader.biHeight);
absWidth = abs(bmi.bmiHeader.biWidth);
if (bmi.bmiHeader.biHeight < 0) {
KdPrint(("PMNTQueryClipbrdBitmap: biHeight=%lx\n",bmi.bmiHeader.biHeight));
}
if (bmi.bmiHeader.biWidth < 0) {
KdPrint(("PMNTQueryClipbrdBitmap: biWidth=%lx\n",bmi.bmiHeader.biWidth));
}
if (bmi.bmiHeader.biPlanes != 1) {
KdPrint(("PMNTQueryClipbrdBitmap: biPlanes=%x\n",bmi.bmiHeader.biPlanes));
bmi.bmiHeader.biPlanes=1;
}
if (bmi.bmiHeader.biCompression) {
KdPrint(("PMNTQueryClipbrdBitmap: biCompression=%lx\n",bmi.bmiHeader.biCompression));
bmi.bmiHeader.biCompression = BI_RGB;
}
if (bmi.bmiHeader.biXPelsPerMeter) {
KdPrint(("PMNTQueryClipbrdBitmap: biXPelsPerMeter=%lx\n",bmi.bmiHeader.biXPelsPerMeter));
bmi.bmiHeader.biXPelsPerMeter = 0;
}
if (bmi.bmiHeader.biYPelsPerMeter) {
KdPrint(("PMNTQueryClipbrdBitmap: biYPelsPerMeter=%lx\n",bmi.bmiHeader.biYPelsPerMeter));
bmi.bmiHeader.biYPelsPerMeter = 0;
}
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
if (bmi.bmiHeader.biBitCount == 16 || bmi.bmiHeader.biBitCount == 32) {
KdPrint(("PMNTQueryClipbrdBitmap: BitCount = %x\n",bmi.bmiHeader.biBitCount));
bmi.bmiHeader.biBitCount = 24;
}
no_of_colors = (bmi.bmiHeader.biBitCount <= 8)
? (1 << bmi.bmiHeader.biBitCount) : 0;
cbBitmapInfo = sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * (no_of_colors));
if (DosAllocSeg (cbBitmapInfo,&selBitmapInfo,0)) {
KdPrint(("PMNTQueryClipbrdBitmap: 1st DosAllocSeg() failed\n"));
goto exit_query_bitmap;
}
pbmi = SELTOFLAT(selBitmapInfo);
pbmi->bmiHeader = bmi.bmiHeader;
cbBuffer = (((bmi.bmiHeader.biBitCount * absWidth) + 31)/32)
* 4 * absHeight;
if (cbBuffer <= _64K) {
if (DosAllocSeg ((USHORT)cbBuffer,&selBuffer,0)) {
KdPrint(("PMNTQueryClipbrdBitmap: 2nd DosAllocSeg() failed\n"));
goto exit_query_bitmap;
}
}
else {
if (DosAllocHuge(cbBuffer / _64K , (USHORT)(cbBuffer % _64K) , &selBuffer, 0L,0)) {
KdPrint(("PMNTQueryClipbrdBitmap: DosAllocHuge() failed\n"));
goto exit_query_bitmap;
}
}
*ppbBuffer = SELTOFLAT(selBuffer);
if (!(GetDIBits(hdc,hbitmap,0,absHeight,*ppbBuffer,pbmi,DIB_RGB_COLORS))){
KdPrint(("PMNTQueryClipbrdBitmap(): 2nd GetDiBits failed\n"));
goto exit_query_bitmap;
}
if (bmi.bmiHeader.biBitCount == 16 || bmi.bmiHeader.biBitCount == 32) {
KdPrint(("PMNTQueryClipbrdBitmap: BitCount = %x\n",bmi.bmiHeader.biBitCount));
bmi.bmiHeader.biBitCount = 24;
}
*ppbmiPM = (PBITMAPCOREINFO) pbmi;
(*ppbmiPM)->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
(*ppbmiPM)->bmciHeader.bcWidth = absWidth;
(*ppbmiPM)->bmciHeader.bcHeight = absHeight;
(*ppbmiPM)->bmciHeader.bcPlanes = 1;
(*ppbmiPM)->bmciHeader.bcBitCount = bmi.bmiHeader.biBitCount;
for (i=0;i<no_of_colors;i++) {
(*ppbmiPM)->bmciColors[i].rgbtBlue = pbmi->bmiColors[i].rgbBlue;
(*ppbmiPM)->bmciColors[i].rgbtGreen = pbmi->bmiColors[i].rgbGreen;
(*ppbmiPM)->bmciColors[i].rgbtRed = pbmi->bmiColors[i].rgbRed;
}
*ppbmiPM = (void *) FLATTOFARPTR((*ppbmiPM));
*ppbBuffer = (void *) FLATTOFARPTR((*ppbBuffer));
rc = (ULONG) TRUE;
exit_query_bitmap:
DeleteDC(hdc);
return(rc);
}
ULONG
PMNTQueryClipbrdFmtInfo(
IN ULONG fmt, OUT PUSHORT pfsFmtInfo)
{
ULONG exist_fmt;
exist_fmt = (*pfsFmtInfo) = 0;
if (fmt == PMNT_CF_TEXT) {
if (exist_fmt = (ULONG) IsClipboardFormatAvailable(CF_TEXT)) {
*pfsFmtInfo = CFI_SELECTOR;
}
}
else if (fmt == PMNT_CF_BITMAP) {
if (exist_fmt = (ULONG) IsClipboardFormatAvailable(CF_BITMAP)) {
*pfsFmtInfo = CFI_HANDLE;
}
}
return(exist_fmt);
}
long FAR PASCAL WndProc(HWND,UINT,WPARAM,LPARAM);
typedef struct _CLIPBRDDATA {
ULONG SemPM;
ULONG SemWin32;
ULONG hwnd;
ULONG fempty;
USHORT QueryFmt;
} CLIPBRDDATA;
typedef CLIPBRDDATA FAR *PCLIPBRDDATA;
PCLIPBRDDATA pClipbrdData=NULL;
ULONG
PMNTWin32Clipbrd(
IN PCLIPBRDDATA ptrdata)
{
static char szAppName[]="PMNTClipboard";
MSG msg;
WNDCLASS wndclass;
pClipbrdData = ptrdata;
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = NULL;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
RegisterClass(&wndclass);
pClipbrdData->hwnd = (ULONG) CreateWindow(szAppName,
"",
0,
-1,
-1,
0,
0,
NULL,
NULL,
NULL,
NULL);
while (GetMessage (&msg,(HWND) pClipbrdData->hwnd,0,0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(msg.wParam);
}
long FAR PASCAL WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
HWND hOwner;
switch (msg) {
case WM_RENDERFORMAT:
if ((pClipbrdData->QueryFmt = (USHORT) wParam) == CF_TEXT
|| pClipbrdData->QueryFmt == CF_BITMAP) {
DosSemSet(&(pClipbrdData->SemPM));
DosSemClear(&(pClipbrdData->SemWin32));
DosSemWait(&(pClipbrdData->SemPM),-1L);
}
return(0);
case WM_DESTROYCLIPBOARD:
hOwner = GetClipboardOwner();
if (hOwner != hwnd) {
// new owner is Win32 app, not PMNT app
pClipbrdData->fempty = TRUE;
DosSemSet(&(pClipbrdData->SemPM));
DosSemClear(&(pClipbrdData->SemWin32));
DosSemWait(&(pClipbrdData->SemPM),-1L);
pClipbrdData->fempty = FALSE;
}
return(0);
}
return(DefWindowProc(hwnd,msg,wParam,lParam));
}
#if 0 // We decided not to use the code below for now
/******************************************************************************
* PMNTCloseRetryPopup: *
* Close the "Wait", "End Task", "Cancel" pop-up dialog opened by the Console*
* when closing a CMD window representing a PM app. *
* *
* Parameters: *
* *
* fClose: 0 - Simulate 'Cancel' *
* Otherwise, 'Wait' *
******************************************************************************/
ULONG
PMNTCloseRetryPopup(
IN ULONG fClose)
{
HWND hwndPopup, hwndParent;
HMODULE modulePopup;
HINSTANCE instancePopup;
USHORT TimeOut = 5;
if (fClose)
fClose = IDRETRY;
else
fClose = IDCANCEL;
hwndPopup = GetTopWindow(NULL); // Get handle of Retry popup
hwndParent = (HWND)GetWindowLong(hwndPopup, GWL_HWNDPARENT);
modulePopup = (HMODULE)GetClassLong(hwndPopup, GCL_HMODULE);
instancePopup = (HINSTANCE)GetWindowLong(hwndPopup, GWL_HINSTANCE);
// DbgPrint("Popup=%x, Parent=%x, Module=%x, instance=%x\n",hwndPopup, hwndParent, modulePopup, instancePopup);
// The pop-up dialog is identified by 3 conditions:
// - has no parent (hwndParent is NULL)
// - modulePopup is NULL
// - instancePopup is NULL (i.e. we got the first instance of this window
// class on the screen)
// WARNING: the present code & comments should be taken with caution since
// they are based on partial knowledge and mostly experimentation.
while (((hwndParent != NULL) || (modulePopup != 0) || (instancePopup != 0))
&& TimeOut--)
{
Sleep(300L);
hwndPopup = GetTopWindow(NULL); // Get handle of Retry popup
hwndParent = (HWND)GetWindowLong(hwndPopup, GWL_HWNDPARENT);
modulePopup = (HMODULE)GetClassLong(hwndPopup, GCL_HMODULE);
instancePopup = (HINSTANCE)GetWindowLong(hwndPopup, GWL_HINSTANCE);
// DbgPrint("Popup=%x, Parent=%x, Module=%x, instance=%x\n",hwndPopup, hwndParent, modulePopup, instancePopup);
}
PostMessage(hwndPopup, WM_COMMAND, (WPARAM)fClose, (LPARAM)0);
return(NO_ERROR);
}
#endif //0
#endif // PMNT