567 lines
10 KiB
C
567 lines
10 KiB
C
/*++
|
||
|
||
Copyright (c) 1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
shortcut.c
|
||
|
||
Abstract:
|
||
|
||
This module contains code to manipulate shortcuts.
|
||
|
||
Author:
|
||
|
||
Wesley Witt (wesw) 24-Jul-1997
|
||
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include <windows.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <shlobj.h>
|
||
#include <shellapi.h>
|
||
#include <commdlg.h>
|
||
#include <winspool.h>
|
||
#include <tchar.h>
|
||
|
||
#include "faxreg.h"
|
||
#include "faxutil.h"
|
||
|
||
|
||
//
|
||
// Cover page filename extension and link filename extension
|
||
//
|
||
|
||
#define CP_FILENAME_EXT TEXT(".cov")
|
||
#define LNK_FILENAME_EXT TEXT(".lnk")
|
||
#define FILENAME_EXT TEXT('.')
|
||
#define MAX_FILENAME_EXT 4
|
||
|
||
//
|
||
// Whether not we've done OLE initialization
|
||
//
|
||
|
||
static BOOL oleInitialized = FALSE;
|
||
|
||
//
|
||
// Find the filename portion given a filename:
|
||
// return a pointer to the '.' character if successful
|
||
// NULL if there is no extension
|
||
//
|
||
|
||
#define FindFilenameExtension(pFilename) _tcsrchr(pFilename, FILENAME_EXT)
|
||
|
||
|
||
static LPTSTR Platforms[] =
|
||
{
|
||
TEXT("Windows NT x86"),
|
||
TEXT("Windows NT R4000"),
|
||
TEXT("Windows NT Alpha_AXP"),
|
||
TEXT("Windows NT PowerPC")
|
||
};
|
||
|
||
|
||
|
||
|
||
VOID
|
||
InitOle(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Perform OLE initialization if necessary
|
||
|
||
Arguments:
|
||
|
||
NONE
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
if (!oleInitialized) {
|
||
|
||
HRESULT hResult = CoInitialize(NULL);
|
||
|
||
if (hResult == S_OK || hResult == S_FALSE) {
|
||
oleInitialized = TRUE;
|
||
} else {
|
||
DebugPrint(( TEXT("OLE initialization failed: %d\n"), hResult ));
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
DeinitOle(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Perform OLE deinitialization if necessary
|
||
|
||
Arguments:
|
||
|
||
NONE
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
if (oleInitialized) {
|
||
CoUninitialize();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
ResolveShortcut(
|
||
LPTSTR pLinkName,
|
||
LPTSTR pFileName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Resolve a shortcut to find the destination file
|
||
|
||
Arguments:
|
||
|
||
pLinkName - Specifies the name of a link file
|
||
pFileName - Points to a buffer for storing the destination filename
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
LPTSTR pExtension;
|
||
HRESULT hResult;
|
||
IShellLink *pShellLink;
|
||
IPersistFile *pPersistFile;
|
||
#ifndef UNICODE
|
||
LPWSTR pLinkNameW;
|
||
#endif
|
||
|
||
//
|
||
// Default to empty string in case of an error
|
||
//
|
||
|
||
*pFileName = 0;
|
||
|
||
if (!oleInitialized) {
|
||
InitOle();
|
||
if (!oleInitialized) {
|
||
DebugPrint(( TEXT("OLE wasn't initialized successfully\n") ));
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Make sure the filename has the .LNK extension
|
||
//
|
||
|
||
if ((pExtension = FindFilenameExtension(pLinkName)) == NULL ||
|
||
_tcsicmp(pExtension, LNK_FILENAME_EXT) != 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Get a pointer to IShellLink interface
|
||
//
|
||
|
||
hResult = CoCreateInstance(&CLSID_ShellLink,
|
||
NULL,
|
||
CLSCTX_INPROC_SERVER,
|
||
&IID_IShellLink,
|
||
&pShellLink);
|
||
|
||
if (SUCCEEDED(hResult)) {
|
||
|
||
//
|
||
// Get a pointer to IPersistFile interface
|
||
//
|
||
|
||
hResult = pShellLink->lpVtbl->QueryInterface(pShellLink,
|
||
&IID_IPersistFile,
|
||
&pPersistFile);
|
||
|
||
if (SUCCEEDED(hResult)) {
|
||
|
||
//
|
||
// Now resolve the link to find the actually file it refers to
|
||
//
|
||
|
||
#ifdef UNICODE
|
||
hResult = pPersistFile->lpVtbl->Load(pPersistFile, pLinkName, STGM_READ);
|
||
#else
|
||
pLinkNameW = AnsiStringToUnicodeString( pLinkName );
|
||
hResult = pPersistFile->lpVtbl->Load(pPersistFile, pLinkNameW, STGM_READ);
|
||
MemFree( pLinkNameW );
|
||
#endif
|
||
|
||
if (SUCCEEDED(hResult)) {
|
||
|
||
hResult = pShellLink->lpVtbl->Resolve(pShellLink, NULL, SLR_NO_UI | 0x00010000);
|
||
|
||
if (SUCCEEDED(hResult))
|
||
pShellLink->lpVtbl->GetPath(pShellLink, pFileName, MAX_PATH, NULL, 0);
|
||
}
|
||
|
||
pPersistFile->lpVtbl->Release(pPersistFile);
|
||
}
|
||
|
||
pShellLink->lpVtbl->Release(pShellLink);
|
||
}
|
||
|
||
return SUCCEEDED(hResult);
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
CreateShortcut(
|
||
LPTSTR pLinkName,
|
||
LPTSTR pFileName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create a shortcut from pLinkName to pFileName
|
||
|
||
Arguments:
|
||
|
||
pLinkName - Name of the link file
|
||
pFileName - Name of the destination file
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
HRESULT hResult;
|
||
IShellLink *pShellLink;
|
||
IPersistFile *pPersistFile;
|
||
#ifndef UNICODE
|
||
LPWSTR pLinkNameW;
|
||
#endif
|
||
|
||
|
||
if (!oleInitialized) {
|
||
InitOle();
|
||
if (!oleInitialized) {
|
||
DebugPrint(( TEXT("OLE wasn't initialized successfully\n") ));
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
hResult = CoCreateInstance(&CLSID_ShellLink,
|
||
NULL,
|
||
CLSCTX_INPROC_SERVER,
|
||
&IID_IShellLink,
|
||
&pShellLink);
|
||
|
||
if (SUCCEEDED(hResult)) {
|
||
|
||
hResult = pShellLink->lpVtbl->QueryInterface(pShellLink,
|
||
&IID_IPersistFile,
|
||
&pPersistFile);
|
||
|
||
if (SUCCEEDED(hResult)) {
|
||
|
||
pShellLink->lpVtbl->SetPath(pShellLink, pFileName);
|
||
#ifdef UNICODE
|
||
hResult = pPersistFile->lpVtbl->Save(pPersistFile, pLinkName, STGM_READ);
|
||
#else
|
||
pLinkNameW = AnsiStringToUnicodeString( pLinkName );
|
||
hResult = pPersistFile->lpVtbl->Save(pPersistFile, pLinkNameW, STGM_READ);
|
||
MemFree( pLinkNameW );
|
||
#endif
|
||
pPersistFile->lpVtbl->Release(pPersistFile);
|
||
}
|
||
|
||
pShellLink->lpVtbl->Release(pShellLink);
|
||
}
|
||
|
||
return SUCCEEDED(hResult);
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
IsCoverPageShortcut(
|
||
LPCTSTR pLinkName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Check if a link is a shortcut to some cover page file
|
||
|
||
Arguments:
|
||
|
||
pLinkName - Specifies the name of a link file
|
||
|
||
Return Value:
|
||
|
||
TRUE if the link file is a shortcut to a cover page file
|
||
FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
LPTSTR pExtension;
|
||
TCHAR filename[MAX_PATH];
|
||
|
||
//
|
||
// Resolve the link if necessary and check if the final filename has
|
||
// the properly extension.
|
||
//
|
||
|
||
return ResolveShortcut((LPTSTR)pLinkName, filename) &&
|
||
(pExtension = FindFilenameExtension(filename)) &&
|
||
_tcsicmp(pExtension, CP_FILENAME_EXT) == 0;
|
||
}
|
||
|
||
|
||
|
||
BOOL GetSpecialPath(
|
||
int nFolder,
|
||
LPTSTR Path
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get a path from a CSIDL constant
|
||
|
||
Arguments:
|
||
|
||
nFolder - CSIDL_ constant
|
||
Path - Buffer to receive the path, assume this buffer is at least MAX_PATH+1 chars large
|
||
|
||
Return Value:
|
||
|
||
TRUE for success.
|
||
FALSE for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
HRESULT hr;
|
||
LPITEMIDLIST pIdl = NULL;
|
||
LPMALLOC IMalloc = NULL;
|
||
BOOL fSuccess = FALSE;
|
||
|
||
hr = SHGetMalloc(&IMalloc);
|
||
if (FAILED(hr) ) {
|
||
DebugPrint(( TEXT("SHGetMalloc() failed, ec = %x\n"),hr));
|
||
goto exit;
|
||
}
|
||
|
||
hr = SHGetSpecialFolderLocation (NULL,
|
||
nFolder,
|
||
&pIdl);
|
||
|
||
if (FAILED(hr) ) {
|
||
DebugPrint((TEXT("SHGetSpecialFolderLocation(%d) failed, ec = %x\n"),nFolder,hr));
|
||
goto exit;
|
||
}
|
||
|
||
hr = SHGetPathFromIDList(pIdl, Path);
|
||
if (FAILED(hr) ) {
|
||
DebugPrint((TEXT("SHGetPAthFromIDList() failed, ec = %x\n"),hr));
|
||
goto exit;
|
||
}
|
||
|
||
fSuccess = TRUE;
|
||
|
||
exit:
|
||
if (IMalloc && pIdl) {
|
||
IMalloc->lpVtbl->Free(IMalloc, (void *) pIdl );
|
||
}
|
||
|
||
if (IMalloc) {
|
||
IMalloc->lpVtbl->Release(IMalloc) ;
|
||
}
|
||
|
||
return fSuccess;
|
||
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
GetClientCpDir(
|
||
LPTSTR CpDir,
|
||
DWORD CpDirSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the client coverpage directory.
|
||
|
||
Arguments:
|
||
|
||
CpDir - buffer to hold the coverpage dir
|
||
CpDirSize - size in bytes of CpDir
|
||
|
||
Return Value:
|
||
|
||
Pointer to the client coverpage direcory.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY hKey;
|
||
LONG rVal;
|
||
DWORD RegType;
|
||
TCHAR PartialPathBuffer[MAX_PATH];
|
||
DWORD dwSize = sizeof(PartialPathBuffer);
|
||
|
||
if (!GetSpecialPath(CSIDL_PERSONAL, CpDir )) {
|
||
return FALSE;
|
||
}
|
||
|
||
rVal = RegOpenKey(
|
||
HKEY_CURRENT_USER,
|
||
REGKEY_FAX_SETUP,
|
||
&hKey
|
||
);
|
||
if (rVal != ERROR_SUCCESS) {
|
||
return FALSE;
|
||
}
|
||
|
||
rVal = RegQueryValueEx(
|
||
hKey,
|
||
REGVAL_CP_LOCATION,
|
||
0,
|
||
&RegType,
|
||
(LPBYTE) PartialPathBuffer,
|
||
&dwSize
|
||
);
|
||
if (rVal != ERROR_SUCCESS) {
|
||
RegCloseKey( hKey );
|
||
return FALSE;
|
||
}
|
||
|
||
RegCloseKey( hKey );
|
||
|
||
|
||
|
||
if (PartialPathBuffer[0] && PartialPathBuffer[_tcslen(PartialPathBuffer)-1] != TEXT('\\')) {
|
||
_tcscat( PartialPathBuffer, TEXT("\\") );
|
||
}
|
||
|
||
ConcatenatePaths(CpDir, PartialPathBuffer);
|
||
|
||
//
|
||
// make sure that directory exists
|
||
//
|
||
MakeDirectory(CpDir);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
GetServerCpDir(
|
||
LPCTSTR ServerName OPTIONAL,
|
||
LPTSTR CpDir,
|
||
DWORD CpDirSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the server coverpage directory.
|
||
|
||
Arguments:
|
||
|
||
ServerName - server name or NULL
|
||
CpDir - buffer to hold the coverpage dir
|
||
CpDirSize - size in bytes of CpDir
|
||
|
||
Return Value:
|
||
|
||
Pointer to the server coverpage direcory.
|
||
|
||
--*/
|
||
|
||
{
|
||
TCHAR tmpcp[MAX_PATH];
|
||
|
||
#undef IDS_COVERPAGE_DIR
|
||
#define IDS_COVERPAGE_DIR 627
|
||
|
||
if (!CpDir) {
|
||
return(FALSE);
|
||
}
|
||
|
||
if (ServerName) {
|
||
wsprintf( tmpcp, TEXT("\\\\%s\\coverpg$"),ServerName);
|
||
} else {
|
||
HINSTANCE hResource;
|
||
TCHAR ResourceDll[MAX_PATH];
|
||
TCHAR RestofPath[MAX_PATH];
|
||
if (!GetSpecialPath(CSIDL_COMMON_DOCUMENTS, tmpcp )) {
|
||
return(FALSE);
|
||
}
|
||
|
||
ExpandEnvironmentStrings(TEXT("%systemroot%\\system32\\faxocm.dll"),ResourceDll,sizeof(ResourceDll)/sizeof(TCHAR));
|
||
|
||
hResource = LoadLibraryEx( ResourceDll, 0, LOAD_LIBRARY_AS_DATAFILE );
|
||
if (!hResource) {
|
||
return(FALSE);
|
||
}
|
||
|
||
if (!MyLoadString(hResource,IDS_COVERPAGE_DIR,RestofPath,sizeof(RestofPath)/sizeof(TCHAR),GetSystemDefaultUILanguage())) {
|
||
FreeLibrary( hResource );
|
||
return(FALSE);
|
||
}
|
||
|
||
ConcatenatePaths(tmpcp, RestofPath);
|
||
|
||
FreeLibrary( hResource );
|
||
|
||
}
|
||
|
||
if ((DWORD) lstrlen(tmpcp) + 1 > CpDirSize) {
|
||
return FALSE;
|
||
}
|
||
|
||
lstrcpy( CpDir,tmpcp ) ;
|
||
|
||
return(TRUE);
|
||
}
|