834 lines
23 KiB
C
834 lines
23 KiB
C
/*++
|
||
|
||
Copyright (c) 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
PutInGrp.C
|
||
|
||
Abstract:
|
||
|
||
Reads the command line to find a file spec (or wildcard spec) and a
|
||
program manager group name and then for each file in the current dir
|
||
that matches the file spec, creates a program item in the specified
|
||
group. If an error occurs and a program item cannot be created, then
|
||
the app returns non-zero (DOS ERRORLEVEL 1) otherwise 0 is returned if
|
||
all matching files are put into the group. The icon name used for the
|
||
program item is the filename (minus extension) of the file found.
|
||
|
||
Author:
|
||
|
||
Bob Watson (a-robw)
|
||
|
||
|
||
Revision History:
|
||
|
||
12 Jun 1994 Created
|
||
|
||
--*/
|
||
//
|
||
// System include files
|
||
//
|
||
#include <windows.h> // windows definitions
|
||
#include <tchar.h> // unicode data and function definitions
|
||
|
||
#include <stdio.h> // printf's etc.
|
||
#include <stdlib.h>
|
||
#include <ddeml.h> // DDEML interface definitions
|
||
|
||
#include "putingrp.h" // application definitions
|
||
|
||
//
|
||
// DDEML constants that depend on UNICODE/ANSI data format
|
||
//
|
||
#if _UNICODE
|
||
#define STRING_CODEPAGE CP_WINUNICODE
|
||
#define APP_TEXT_FORMAT CF_UNICODETEXT
|
||
#else
|
||
#define STRING_CODEPAGE CP_WINANSI
|
||
#define APP_TEXT_FORMAT CF_TEXT
|
||
#endif
|
||
//
|
||
// other application constants
|
||
//
|
||
// time to wait for a dde command to complete (10 sec.)
|
||
//
|
||
#define APP_DDE_TIMEOUT 10000
|
||
//
|
||
// Small buffer size used for general purpose temporary buffers
|
||
//
|
||
#define SMALL_BUFFER_SIZE 1024
|
||
//
|
||
// Large buffer size used for general purpose temporary buffers
|
||
//
|
||
#define BIG_BUFFER_SIZE (16 * SMALL_BUFFER_SIZE)
|
||
//
|
||
// number of times to retry a DDE command before giving up
|
||
//
|
||
#define APP_RETRY_COUNT 5
|
||
//
|
||
// number of buffers in GetStringResource function. These buffers
|
||
// are used sequentially to allow up to this many calls before a
|
||
// buffer is overwritten.
|
||
//
|
||
#define RES_STRING_BUFFER_COUNT 4
|
||
//
|
||
// time delay between DDE EXECUTE calls
|
||
// 500 = .5 sec
|
||
//
|
||
#define PAUSE_TIME 500
|
||
|
||
LPCTSTR
|
||
GetFileName (
|
||
IN LPCTSTR szFileName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
returns a buffer that contains the filename without the
|
||
period or extension. The filename returned has the
|
||
first character upper-cased and all other characters are
|
||
kept the same.
|
||
|
||
Arguments:
|
||
|
||
IN LPCTSTR szFileName
|
||
pointer to a filename string. This is assumed to be just
|
||
a filename with no path information.
|
||
|
||
Return Value:
|
||
|
||
pointer to a buffer containing the filename.
|
||
|
||
--*/
|
||
{
|
||
static TCHAR szReturnBuffer[MAX_PATH]; // buffer for result
|
||
LPCTSTR szSrc; // pointer into source string
|
||
LPTSTR szDest; // pointer into destination string
|
||
BOOL bFirst = TRUE; // used to tell when 1st char has been UC'd
|
||
|
||
szSrc = szFileName;
|
||
szDest = &szReturnBuffer[0];
|
||
*szDest = 0; // clear old contents
|
||
// go through source until end or "." whichever comes first.
|
||
while ((*szSrc != TEXT('.')) && (*szSrc != 0)) {
|
||
*szDest++ = *szSrc++;
|
||
// uppercase first letter
|
||
if (bFirst) {
|
||
*szDest = 0;
|
||
_tcsupr (&szReturnBuffer[0]);
|
||
bFirst = FALSE;
|
||
}
|
||
}
|
||
*szDest = 0;
|
||
return (LPCTSTR)szReturnBuffer;
|
||
}
|
||
|
||
LPCTSTR
|
||
GetStringResource (
|
||
IN UINT nId
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Used to load a string resource for this app so it can be used as a
|
||
string constant. NOTE the resulting string should be copied into
|
||
a local buffer since the contents of the buffer returned by this
|
||
routine may change in subsequent calls.
|
||
|
||
Arguments:
|
||
|
||
IN UINT nId
|
||
Resource ID to return.
|
||
|
||
Return Value:
|
||
|
||
pointer to string referenced by Resource ID value.
|
||
|
||
--*/
|
||
{
|
||
static TCHAR szStringBuffer[RES_STRING_BUFFER_COUNT][SMALL_BUFFER_SIZE];
|
||
static DWORD dwBufferNdx; // current buffer in use
|
||
LPTSTR szBuffer; // pointer to current buffer
|
||
int nLength; // length of string found
|
||
|
||
// select new buffer
|
||
dwBufferNdx++; // go to next index
|
||
dwBufferNdx %= RES_STRING_BUFFER_COUNT; // keep within bounds
|
||
szBuffer = &szStringBuffer[dwBufferNdx][0]; // set pointer
|
||
|
||
// get buffer
|
||
nLength = LoadString (
|
||
(HINSTANCE)GetModuleHandle(NULL),
|
||
nId,
|
||
szBuffer,
|
||
SMALL_BUFFER_SIZE);
|
||
|
||
// return pointer to buffer in use
|
||
return (LPCTSTR)szBuffer;
|
||
}
|
||
|
||
VOID
|
||
DisplayUsage (
|
||
VOID
|
||
)
|
||
{
|
||
UINT nString;
|
||
|
||
for (nString = APP_USAGE_START; nString <= APP_USAGE_END; nString++){
|
||
_tprintf (GetStringResource(nString));
|
||
}
|
||
}
|
||
|
||
BOOL
|
||
IsProgmanWindow (
|
||
IN HWND hWnd,
|
||
IN LPARAM lParam
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Function called by EnumWindows function to tell if the
|
||
Program Manger window has been found. A match is determined
|
||
by comparing the window caption (so it's not fool proof).
|
||
|
||
|
||
Arguments:
|
||
|
||
IN HWND hWnd
|
||
handle of window to test
|
||
|
||
IN LPARAM lParam
|
||
address of window handle variable to be loaded when program
|
||
manager window is found. set to NULL if this window is NOT
|
||
the Program Manager
|
||
|
||
Return Value:
|
||
|
||
TRUE if this is NOT the Program Manager window
|
||
FALSE if this IS the Program Manager window
|
||
(this is to accomodate the EnumWindows logic)
|
||
|
||
--*/
|
||
{
|
||
static TCHAR szWindowName[MAX_PATH]; // buffer to write this window's title
|
||
DWORD dwProgmanTitleLen; // length of "Program Manager"
|
||
LPTSTR szProgmanTitle; // pointer to title string
|
||
HWND *hwndReturn; // return window handle pointer
|
||
|
||
hwndReturn = (HWND *)lParam; // cast LPARAM to HWND *
|
||
if (hwndReturn != NULL) {
|
||
*hwndReturn = NULL; // initialize to NULL handle
|
||
}
|
||
|
||
if (IsWindow (hWnd)) {
|
||
// only check windows
|
||
//
|
||
// get title string to match against
|
||
szProgmanTitle = (LPTSTR)GetStringResource (APP_PROGMAN_TITLE);
|
||
dwProgmanTitleLen = lstrlen(szProgmanTitle);
|
||
//
|
||
// get title of this window
|
||
GetWindowText (hWnd, &szWindowName[0], MAX_PATH);
|
||
|
||
// check the length
|
||
if ((DWORD)lstrlen(&szWindowName[0]) < dwProgmanTitleLen) {
|
||
// this is too short to match
|
||
return TRUE; // not Program Manager, get next window
|
||
} else {
|
||
// make window name same length as program manager string
|
||
szWindowName[dwProgmanTitleLen] = 0;
|
||
// compare window name to match title string
|
||
if (lstrcmpi(&szWindowName[0], szProgmanTitle) == 0) {
|
||
// it's a match
|
||
if (hwndReturn != NULL) {
|
||
*hwndReturn = hWnd;
|
||
}
|
||
return FALSE; // found it so leave
|
||
} else {
|
||
return TRUE; // not this one, so keep going
|
||
}
|
||
}
|
||
} else {
|
||
return TRUE; // not this one, so keep going
|
||
}
|
||
}
|
||
|
||
BOOL
|
||
RestoreProgmanWindow (
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Activates and Restores the Program Manager window and makes it the
|
||
foreground app.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
TRUE if window restored
|
||
FALSE if window not found
|
||
|
||
--*/
|
||
{
|
||
HWND hwndProgman;
|
||
|
||
// find progman and restore it
|
||
|
||
EnumWindows (IsProgmanWindow, (LPARAM)&hwndProgman);
|
||
|
||
if (IsWindow (hwndProgman)) {
|
||
// if iconic, then restore
|
||
if (IsIconic(hwndProgman)) {
|
||
ShowWindow (hwndProgman, SW_RESTORE);
|
||
}
|
||
// make the foreground app.
|
||
SetForegroundWindow (hwndProgman);
|
||
return TRUE;
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
HDDEDATA CALLBACK
|
||
DdeCallback (
|
||
IN UINT wType,
|
||
IN UINT wFmt,
|
||
IN HCONV hConv,
|
||
IN HSZ hsz1,
|
||
IN HSZ hsz2,
|
||
IN HDDEDATA hData,
|
||
IN DWORD lData1,
|
||
IN DWORD lData2
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Generic Callback function required by DDEML calls
|
||
|
||
Arguments:
|
||
|
||
See WinHelp
|
||
|
||
Return Value:
|
||
|
||
See WinHelp
|
||
|
||
--*/
|
||
{
|
||
switch (wType) {
|
||
case XTYP_REGISTER:
|
||
case XTYP_UNREGISTER:
|
||
return (HDDEDATA)NULL;
|
||
|
||
case XTYP_ADVDATA:
|
||
// received when new data is available
|
||
return (HDDEDATA)DDE_FACK;
|
||
|
||
case XTYP_XACT_COMPLETE:
|
||
// received when an async transaction is complete
|
||
return (HDDEDATA)NULL;
|
||
|
||
case XTYP_DISCONNECT:
|
||
// connection termination has been requested
|
||
return (HDDEDATA)NULL;
|
||
|
||
default:
|
||
return (HDDEDATA)NULL;
|
||
}
|
||
}
|
||
|
||
HCONV
|
||
ConnectToProgman (
|
||
IN DWORD dwInst
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Establishes a DDE connection to the program manager's DDE
|
||
server.
|
||
|
||
Arguments:
|
||
|
||
IN DWORD dwInst
|
||
DDEML Instance as returned by DdeInitialize call
|
||
|
||
Return Value:
|
||
|
||
Handle to conversation if successful,
|
||
0 if not
|
||
|
||
--*/
|
||
{
|
||
HSZ hszProgman1;
|
||
HSZ hszProgman2;
|
||
HCONV hConversation;
|
||
CONVCONTEXT ccConversation;
|
||
|
||
// init conversation context buffer
|
||
ccConversation.cb = sizeof(CONVCONTEXT);
|
||
ccConversation.wFlags = 0;
|
||
ccConversation.wCountryID = 0;
|
||
ccConversation.iCodePage = 0;
|
||
ccConversation.dwLangID = 0L;
|
||
ccConversation.dwSecurity = 0L;
|
||
ccConversation.qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
||
ccConversation.qos.ImpersonationLevel = SecurityImpersonation;
|
||
ccConversation.qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
|
||
ccConversation.qos.EffectiveOnly = TRUE;
|
||
|
||
// get server name
|
||
hszProgman1 = DdeCreateStringHandle (dwInst,
|
||
(LPTSTR)GetStringResource (APP_SERVER),
|
||
STRING_CODEPAGE);
|
||
|
||
if (hszProgman1 != 0) {
|
||
// get topic name
|
||
hszProgman2 = DdeCreateStringHandle (dwInst,
|
||
(LPTSTR)GetStringResource (APP_TOPIC),
|
||
STRING_CODEPAGE);
|
||
|
||
if (hszProgman2 != 0) {
|
||
// connect to server
|
||
hConversation = DdeConnect (
|
||
dwInst,
|
||
hszProgman1,
|
||
hszProgman2,
|
||
&ccConversation);
|
||
|
||
// free string handle
|
||
DdeFreeStringHandle (dwInst, hszProgman2);
|
||
}
|
||
// free string handle
|
||
DdeFreeStringHandle (dwInst, hszProgman1);
|
||
}
|
||
|
||
return hConversation; // return handle
|
||
}
|
||
|
||
BOOL
|
||
CreateAndShowGroup (
|
||
IN DWORD dwInst,
|
||
IN HCONV hConversation,
|
||
IN LPCTSTR szGroupName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
creates and activates the program manager group specified
|
||
in the argument list
|
||
|
||
Arguments:
|
||
|
||
IN DWORD dwInst
|
||
Instance ID returned from DdeInitialize
|
||
|
||
IN HCONV hConversation
|
||
Handle to the current DDE conversation
|
||
|
||
IN LPCTSTR szGroupName
|
||
Pointer to string containing name of program manager group to
|
||
create and/or activate
|
||
|
||
Return Value:
|
||
|
||
TRUE if operation succeeded
|
||
FALSE if not
|
||
|
||
--*/
|
||
{
|
||
LPTSTR szCmdBuffer; // DDE command string to send
|
||
LPTSTR szCmdFmt; // DDE command format for sprintf
|
||
DWORD dwCmdLength; // size of command string
|
||
BOOL bResult; // result of function calls
|
||
DWORD dwTransactionResult; // result of Command
|
||
|
||
// allocate temporary memory buffers
|
||
szCmdFmt = GlobalAlloc (GPTR, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
||
szCmdBuffer = GlobalAlloc (GPTR, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
||
|
||
if ((szCmdBuffer != NULL) &&
|
||
(szCmdFmt != NULL)) {
|
||
|
||
// get command format string
|
||
lstrcpy (szCmdFmt, GetStringResource(APP_CREATE_AND_SHOW_FMT));
|
||
|
||
// format command to include desired group name
|
||
dwCmdLength = _stprintf (szCmdBuffer, szCmdFmt, szGroupName) + 1;
|
||
dwCmdLength *= sizeof(TCHAR) ;
|
||
|
||
// create group or activate group if it already exists
|
||
// send command to server
|
||
Sleep (PAUSE_TIME);
|
||
bResult = DdeClientTransaction (
|
||
(LPBYTE)szCmdBuffer,
|
||
dwCmdLength,
|
||
hConversation,
|
||
0L,
|
||
APP_TEXT_FORMAT,
|
||
XTYP_EXECUTE,
|
||
APP_DDE_TIMEOUT,
|
||
&dwTransactionResult);
|
||
|
||
#if DEBUG_OUT
|
||
if (!bResult) {
|
||
_tprintf (GetStringResource (APP_DDE_EXECUTE_ERROR_FMT),
|
||
DdeGetLastError(dwInst),
|
||
szCmdBuffer);
|
||
}
|
||
#endif
|
||
|
||
// now activate the group
|
||
// get the command format string
|
||
lstrcpy (szCmdFmt, GetStringResource(APP_RESTORE_GROUP_FMT));
|
||
|
||
// create the command that includes the group name
|
||
dwCmdLength = _stprintf (szCmdBuffer, szCmdFmt, szGroupName) + 1;
|
||
dwCmdLength *= sizeof(TCHAR);
|
||
|
||
// send command to server
|
||
Sleep (PAUSE_TIME);
|
||
bResult = DdeClientTransaction (
|
||
(LPBYTE)szCmdBuffer,
|
||
dwCmdLength,
|
||
hConversation,
|
||
0L,
|
||
APP_TEXT_FORMAT,
|
||
XTYP_EXECUTE,
|
||
APP_DDE_TIMEOUT,
|
||
&dwTransactionResult);
|
||
|
||
#if DEBUG_OUT
|
||
if (!bResult) {
|
||
_tprintf (GetStringResource (APP_DDE_EXECUTE_ERROR_FMT),
|
||
DdeGetLastError(dwInst),
|
||
szCmdBuffer);
|
||
}
|
||
#endif
|
||
|
||
// free global memory buffers
|
||
GlobalFree (szCmdBuffer);
|
||
GlobalFree (szCmdFmt);
|
||
return bResult;
|
||
} else {
|
||
// unable to allocate memory buffers so return error
|
||
SetLastError (ERROR_OUTOFMEMORY);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
BOOL
|
||
LoadFilesToGroup (
|
||
IN DWORD dwInst,
|
||
IN HCONV hConversation,
|
||
IN LPCTSTR szFileSpec,
|
||
IN LPCTSTR szGroupName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Searches the current directory for the file(s) that match the
|
||
fileSpec argument and creates program items the program
|
||
manager group specified by szGroupName.
|
||
|
||
Arguments:
|
||
|
||
IN DWORD dwInst
|
||
DDEML instance handle returned by DdeInitialize
|
||
|
||
IN HCONV hConversation
|
||
Handle to current conversation with DDE Server
|
||
|
||
IN LPCTSTR szFileSpec
|
||
file spec to look up for program items
|
||
|
||
IN LPCTSTR szGroupName
|
||
program manager group to add items to
|
||
|
||
Return Value:
|
||
|
||
TRUE if all items loaded successfully
|
||
FALSE of one or more items did not get installed in Program Manager
|
||
|
||
--*/
|
||
{
|
||
WIN32_FIND_DATA fdSearchData; // search data struct for file search
|
||
HANDLE hFileSearch; // file search handle
|
||
BOOL bSearchResult; // results of current file lookup
|
||
BOOL bResult; // function return
|
||
BOOL bReturn = TRUE; // value returned to calling fn.
|
||
LPTSTR szCmdBuffer; // buffer for one command
|
||
LPTSTR szCmdFmt; // command format buffer for sprintf
|
||
DWORD dwCmdLength; // length of command buffer
|
||
DWORD dwBufferUsed; // chars in DdeCmd that have been used
|
||
DWORD dwTransaction; // returned by DdeClientTransaction
|
||
DWORD dwTransactionResult; // result code
|
||
|
||
// Allocate global memory
|
||
szCmdBuffer = GlobalAlloc (GPTR, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
||
szCmdFmt = GlobalAlloc (GPTR, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
||
|
||
if ((szCmdBuffer != NULL) &&
|
||
(szCmdFmt != NULL)) {
|
||
// get single entry command format for sprintf
|
||
lstrcpy (szCmdFmt, GetStringResource(APP_ADD_PROGRAM_FMT));
|
||
|
||
// start file search
|
||
hFileSearch = FindFirstFile (szFileSpec, &fdSearchData);
|
||
|
||
if (hFileSearch != INVALID_HANDLE_VALUE) {
|
||
// file search initialized OK so start processing files
|
||
dwBufferUsed = 0;
|
||
bSearchResult = TRUE;
|
||
while (bSearchResult) {
|
||
// make sure it's a real file and not a dir or a
|
||
// temporary file
|
||
|
||
if (!((fdSearchData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
||
(fdSearchData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY))) {
|
||
|
||
// make a command for this file
|
||
dwCmdLength = _stprintf (szCmdBuffer, szCmdFmt,
|
||
fdSearchData.cFileName,
|
||
GetFileName(fdSearchData.cFileName)) + 1;
|
||
dwCmdLength *= sizeof(TCHAR);
|
||
dwTransactionResult = 0;
|
||
Sleep (PAUSE_TIME);
|
||
dwTransaction = DdeClientTransaction (
|
||
(LPBYTE)szCmdBuffer,
|
||
dwCmdLength,
|
||
hConversation,
|
||
0L,
|
||
APP_TEXT_FORMAT,
|
||
XTYP_EXECUTE,
|
||
APP_DDE_TIMEOUT,
|
||
&dwTransactionResult);
|
||
|
||
if (dwTransaction > 0) {
|
||
_tprintf (GetStringResource (APP_ADD_SUCCESS_FMT),
|
||
fdSearchData.cFileName, szGroupName);
|
||
bResult = TRUE;
|
||
} else {
|
||
_tprintf (GetStringResource (APP_ADD_ERROR_FMT),
|
||
fdSearchData.cFileName, szGroupName);
|
||
bResult = FALSE;
|
||
}
|
||
if (!bResult) {
|
||
#if DEBUG_OUT
|
||
_tprintf (GetStringResource (APP_DDE_EXECUTE_ERROR_FMT),
|
||
DdeGetLastError(dwInst),
|
||
szDdeCmd);
|
||
#endif
|
||
// at least one entry didn't work so set return value
|
||
bReturn = FALSE;
|
||
}
|
||
}
|
||
// get next matching file
|
||
bSearchResult = FindNextFile (hFileSearch, &fdSearchData);
|
||
}
|
||
}
|
||
// free global memory
|
||
GlobalFree (szCmdBuffer);
|
||
GlobalFree (szCmdFmt);
|
||
return bReturn;
|
||
} else {
|
||
SetLastError (ERROR_OUTOFMEMORY);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
BOOL
|
||
SaveNewGroup (
|
||
IN DWORD dwInst,
|
||
IN HCONV hConversation,
|
||
IN LPCTSTR szGroupName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sends the Reload command to save and reload the new group. This will
|
||
save the information.
|
||
|
||
Arguments:
|
||
|
||
IN DWORD dwInst
|
||
DDEML instance handle returned by DdeInitialize
|
||
|
||
IN HCONV hConversation
|
||
Handle to current conversation with DDE Server
|
||
|
||
IN LPCTSTR szGroupName
|
||
program manager group to add items to
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful
|
||
FALSE if not
|
||
|
||
--*/
|
||
{
|
||
LPTSTR szCmdBuffer; // DDE command string to send
|
||
LPTSTR szCmdFmt; // DDE command format for sprintf
|
||
DWORD dwCmdLength; // size of command string
|
||
BOOL bResult; // result of function calls
|
||
DWORD dwTransactionResult; // result of Command
|
||
|
||
// allocate temporary memory buffers
|
||
szCmdFmt = GlobalAlloc (GPTR, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
||
szCmdBuffer = GlobalAlloc (GPTR, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
||
|
||
if ((szCmdBuffer != NULL) &&
|
||
(szCmdFmt != NULL)) {
|
||
|
||
// get command format string
|
||
lstrcpy (szCmdFmt, GetStringResource(APP_RELOAD_GROUP_FMT));
|
||
|
||
// format command to include desired group name
|
||
dwCmdLength = _stprintf (szCmdBuffer, szCmdFmt, szGroupName) + 1;
|
||
dwCmdLength *= sizeof(TCHAR);
|
||
|
||
// create group or activate group if it already exists
|
||
// send command to server
|
||
Sleep (PAUSE_TIME);
|
||
bResult = DdeClientTransaction (
|
||
(LPBYTE)szCmdBuffer,
|
||
dwCmdLength,
|
||
hConversation,
|
||
0L,
|
||
APP_TEXT_FORMAT,
|
||
XTYP_EXECUTE,
|
||
APP_DDE_TIMEOUT,
|
||
&dwTransactionResult);
|
||
|
||
return bResult;
|
||
} else {
|
||
SetLastError (ERROR_OUTOFMEMORY);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
int
|
||
__cdecl main (
|
||
int argc,
|
||
char **argv
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Main entry point for command line
|
||
|
||
Arguments:
|
||
|
||
IN int argc
|
||
count of arguments passed in from command line
|
||
|
||
IN char *argv[]
|
||
array of pointers to each command line argument
|
||
argv[0] = this program'e .exe path
|
||
argv[1] = file(s) to put in group
|
||
argv[2] = group to create/load
|
||
|
||
Return Value:
|
||
|
||
0 if all files matching the path are successfully loaded into progman
|
||
non-zero if one or more files did not have a progman item created
|
||
|
||
--*/
|
||
{
|
||
DWORD dwInstId = 0; // DDEML Instance
|
||
UINT nReturn; // return value
|
||
BOOL bResult; // function return value
|
||
HCONV hConversation; // handle to DDE conversation
|
||
LPTSTR szFiles; // file path read from command line
|
||
LPTSTR szGroup; // group name read from command line
|
||
|
||
if (argc < 3) {
|
||
// check for correct command line arg count
|
||
DisplayUsage();
|
||
return ERROR_BAD_COMMAND;
|
||
}
|
||
|
||
// allocate buffers for command line arguments
|
||
szFiles = GlobalAlloc (GPTR, (strlen(argv[1]) + 1) * sizeof(TCHAR));
|
||
szGroup = GlobalAlloc (GPTR, (strlen(argv[2]) + 1) * sizeof(TCHAR));
|
||
|
||
if ((szFiles == NULL) || (szGroup == NULL)) {
|
||
return ERROR_OUTOFMEMORY;
|
||
}
|
||
|
||
// read in command line arguments using appropriate function
|
||
#if _UNICODE
|
||
mbstowcs (szFiles, argv[1], lstrlenA(argv[1]));
|
||
mbstowcs (szGroup, argv[2], lstrlenA(argv[2]));
|
||
#else
|
||
lstrcpyA (szFiles, argv[1]);
|
||
lstrcpyA (szGroup, argv[2]);
|
||
#endif
|
||
|
||
// make Program Manager window the foreground app and restore it's size
|
||
RestoreProgmanWindow ();
|
||
|
||
// begin DDEML session
|
||
nReturn = DdeInitialize (&dwInstId,
|
||
(PFNCALLBACK)DdeCallback,
|
||
APPCMD_CLIENTONLY,
|
||
0L);
|
||
|
||
if (nReturn == DMLERR_NO_ERROR) {
|
||
// connect to Program Manager DDE server
|
||
hConversation = ConnectToProgman (dwInstId);
|
||
|
||
if (hConversation != 0) {
|
||
bResult = DdeEnableCallback (dwInstId, hConversation,
|
||
EC_ENABLEALL);
|
||
|
||
// create program group
|
||
if (CreateAndShowGroup (dwInstId, hConversation, szGroup)) {
|
||
// load selected files into group
|
||
if (!LoadFilesToGroup (dwInstId, hConversation, szFiles, szGroup)) {
|
||
// 1 or more files did not get a program item
|
||
nReturn = ERROR_CAN_NOT_COMPLETE;
|
||
} else {
|
||
SaveNewGroup (dwInstId, hConversation, szGroup);
|
||
// all files were loaded into program manager successfully
|
||
nReturn = ERROR_SUCCESS;
|
||
}
|
||
// that's it so close conversation handle
|
||
DdeDisconnect (hConversation);
|
||
} else {
|
||
// unable to create program group
|
||
nReturn = ERROR_CAN_NOT_COMPLETE;
|
||
}
|
||
} else {
|
||
// unablet to establish conversation
|
||
nReturn = ERROR_CAN_NOT_COMPLETE;
|
||
}
|
||
|
||
// terminate DDEML session
|
||
if (!DdeUninitialize (dwInstId)) {
|
||
nReturn = ERROR_CAN_NOT_COMPLETE;
|
||
}
|
||
}
|
||
|
||
// free global buffers
|
||
GlobalFree (szFiles);
|
||
GlobalFree (szGroup);
|
||
|
||
// return value to command shell
|
||
return nReturn;
|
||
}
|