|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Abstract:
This module provides utilities useful for Directory Service interactions
Author:
Steve Wilson (NT) November 1997
Revision History:
--*/
#define INC_OLE2
#include "precomp.h"
#pragma hdrstop
#include "client.h"
#include "pubprn.hxx"
#include "varconv.hxx"
#include "property.hxx"
#include "dsutil.hxx"
#include "winsprlp.h"
#include "dnsapi.h"
#define DN_SPECIAL_CHARS L",=\r\n+<>#;\"\\"
#define DN_SPECIAL_FILTER_CHARS L"\\*()"
PWSTR GetUNCName( HANDLE hPrinter ) { PPRINTER_INFO_2 pInfo2 = NULL; DWORD cbNeeded; PWSTR pszUNCName = NULL;
if (!GetPrinter(hPrinter, 2, (PBYTE) pInfo2, 0, &cbNeeded)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto error; }
if (!(pInfo2 = (PPRINTER_INFO_2) AllocSplMem(cbNeeded))) goto error;
if (!GetPrinter(hPrinter, 2, (PBYTE) pInfo2, cbNeeded, &cbNeeded)) goto error;
// pPrinterName is already in correct UNC format since we
// opened handle with UNC name: just copy it
cbNeeded = wcslen(pInfo2->pPrinterName) + 1; cbNeeded *= sizeof(WCHAR);
if (!(pszUNCName = (PWSTR) AllocSplMem(cbNeeded))) goto error;
StringCbCopy(pszUNCName, cbNeeded, pInfo2->pPrinterName);
error:
if (pInfo2) FreeSplMem(pInfo2);
return pszUNCName; }
HRESULT CreateEscapedDN( PCWSTR pszIn, PWSTR *ppEscapedString ) { PWSTR pszOut = NULL; PWSTR psz; DWORD cch; HRESULT hRet = S_OK;
//
// Count special characters
//
for (cch = 0, psz = (PWSTR) pszIn ; psz = wcspbrk(psz, DN_SPECIAL_FILTER_CHARS) ; ++cch, ++psz) { //
// Empty body
//
} //
// Add in length of input string
// 2 = (\5c) - '\'
//
cch = (wcslen(pszIn) + cch*2 + 1);
//
// Allocate output buffer and replace special chars with \HexEquivalent
// Ex: replace \ with \5c , ( with \28
//
if (pszOut = (PWSTR) AllocSplMem(cch * sizeof(WCHAR))) { size_t cchRemaining = cch; PWSTR pszO;
for(psz = (PWSTR) pszIn, pszO = pszOut ; *psz ; ++psz) { if (wcschr(DN_SPECIAL_FILTER_CHARS, *psz)) { if (FAILED(hRet = StringCchPrintfEx(pszO, cchRemaining, &pszO, &cchRemaining, STRSAFE_NULL_ON_FAILURE, L"\\%x", *psz))) { break; } } else { *pszO++ = *psz;
cchRemaining--; } } *pszO = L'\0'; } else { hRet = E_OUTOFMEMORY; }
if (SUCCEEDED(hRet)) { *ppEscapedString = pszOut; } else { *ppEscapedString = NULL;
FreeSplMem(pszOut); }
return hRet; }
DWORD PrintQueueExists( HWND hwnd, HANDLE hPrinter, PWSTR pszUNCName, DWORD dwAction, PWSTR pszTargetDN, PWSTR *ppszObjectDN ) { HRESULT hr = S_OK; DWORD dwRet = ERROR_SUCCESS; WCHAR szSearchPattern[MAX_UNC_PRINTER_NAME + 50]; WCHAR szFullUNCName[MAX_UNC_PRINTER_NAME]; PWSTR pNames[2]; WCHAR szName[MAX_PATH + 1]; PWSTR pszSearchRoot = NULL; PWSTR pszUNCNameSearch = NULL; IDirectorySearch *pDSSearch = NULL; DS_NAME_RESULT *pDNR = NULL; DOMAIN_CONTROLLER_INFO *pDCI = NULL; HANDLE hDS = NULL; ADS_SEARCH_HANDLE hSearchHandle = NULL; ADS_SEARCH_COLUMN ADsPath; ADS_SEARCH_COLUMN UNCName; PWSTR pszAttributes[] = {L"ADsPath", L"UNCName"}; DWORD nSize; BOOL bRet = FALSE; BOOL bDeleteDuplicate = FALSE; PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDsRole = NULL;
dwRet = DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *) &pDsRole);
if (dwRet != ERROR_SUCCESS) goto error;
StringCchPrintf(szName, COUNTOF(szName), L"%ws\\", pDsRole->DomainNameFlat);
pNames[0] = szName; pNames[1] = NULL;
dwRet = Bind2DS(&hDS, &pDCI, DS_GC_SERVER_REQUIRED); if (dwRet != ERROR_SUCCESS) goto error;
if (!(DsCrackNames( hDS, DS_NAME_NO_FLAGS, DS_UNKNOWN_NAME, DS_FQDN_1779_NAME, 1, &pNames[0], &pDNR) == ERROR_SUCCESS)) {
dwRet = GetLastError(); goto error; }
if (pDNR->rItems[0].status != DS_NAME_NO_ERROR) { if (pDNR->rItems[0].status == DS_NAME_ERROR_RESOLVING) dwRet = ERROR_PATH_NOT_FOUND; else dwRet = pDNR->rItems[0].status;
goto error; }
// GC:// + pDCName + 1
nSize = (wcslen(pDNR->rItems[0].pName) + 6)*sizeof(WCHAR);
if (!(pszSearchRoot = (PWSTR) AllocSplMem(nSize))) { dwRet = GetLastError(); goto error; }
StringCbPrintf(pszSearchRoot, nSize, L"GC://%ws", pDNR->rItems[0].pName);
hr = ADsGetObject( pszSearchRoot, IID_IDirectorySearch, (void **)&pDSSearch); BAIL_ON_FAILURE(hr);
if (FAILED(hr = CreateEscapedDN(pszUNCName, &pszUNCNameSearch))) { dwRet = SCODE_CODE(hr); goto error; }
StringCchPrintf(szSearchPattern, COUNTOF(szSearchPattern), L"(&(objectClass=printQueue)(uNCName=%ws))", pszUNCNameSearch);
hr = pDSSearch->ExecuteSearch( szSearchPattern, pszAttributes, sizeof(pszAttributes)/sizeof *pszAttributes, &hSearchHandle); BAIL_ON_FAILURE(hr);
hr = pDSSearch->GetNextRow(hSearchHandle); BAIL_ON_FAILURE(hr);
while (hr != S_ADS_NOMORE_ROWS) {
hr = pDSSearch->GetColumn( hSearchHandle, L"ADsPath", &ADsPath );
if (hr == S_OK) {
hr = pDSSearch->GetColumn( hSearchHandle, L"UNCName", &UNCName );
if (hr == S_OK) {
switch (dwAction) { case PUBLISHPRINTER_QUERY: { WCHAR szDuplicateFormat[MAX_PATH]; WCHAR szBoxTitle[MAX_PATH]; if (LoadString(hInst, IDS_DUPLICATE_PRINTQUEUE, szDuplicateFormat, COUNTOF(szDuplicateFormat)) && LoadString(hInst, IDS_DUPLICATE_PRINTQUEUE_TITLE, szBoxTitle, COUNTOF(szDuplicateFormat))) { PWSTR pszCanonicalSource = NULL; PWSTR pszCanonicalTarget = NULL; PWSTR pszDuplicate = NULL;
FQDN2Canonical(ADsPath.pADsValues->DNString, &pszCanonicalSource); FQDN2Canonical(pszTargetDN, &pszCanonicalTarget);
PWSTR pszOne = ADsPath.pADsValues->DNString; PWSTR pszTwo = pszTargetDN; if (pszCanonicalSource && pszCanonicalTarget) { pszOne = pszCanonicalSource; pszTwo = pszCanonicalTarget; } nSize = 1 + wcslen(szDuplicateFormat) + wcslen(pszOne) + wcslen(pszTwo); if (pszDuplicate = (PWSTR) AllocSplMem(nSize * sizeof(WCHAR))) { StringCchPrintf(pszDuplicate, nSize, szDuplicateFormat, pszOne, pszTwo);
dwRet = ERROR_SUCCESS; } else { dwRet = GetLastError(); } FreeSplStr(pszCanonicalSource); FreeSplStr(pszCanonicalTarget);
if (dwRet == ERROR_SUCCESS) { dwRet = MessageBox(hwnd, pszDuplicate, szBoxTitle, MB_YESNO);
bDeleteDuplicate = (dwRet == IDYES); dwRet = (dwRet == IDYES) ? ERROR_SUCCESS : ERROR_CANCELLED; }
FreeSplMem(pszDuplicate); } else { dwRet = GetLastError(); }
break; }
case PUBLISHPRINTER_DELETE_DUPLICATES: { bDeleteDuplicate = TRUE; break; }
case PUBLISHPRINTER_FAIL_ON_DUPLICATE: { bDeleteDuplicate = FALSE;
if (ppszObjectDN) { if (!(*ppszObjectDN = AllocGlobalStr(ADsPath.pADsValues->DNString))) { dwRet = GetLastError(); goto error; } }
dwRet = ERROR_FILE_EXISTS; break; }
case PUBLISHPRINTER_IGNORE_DUPLICATES: { bDeleteDuplicate = FALSE; break; } default: { bDeleteDuplicate = FALSE; dwRet = ERROR_INVALID_PARAMETER; break; } }
if (bDeleteDuplicate) { hr = DeleteDSObject(ADsPath.pADsValues->DNString);
if ( hr == ERROR_DS_NO_SUCH_OBJECT ) { hr = S_OK; } }
pDSSearch->FreeColumn(&UNCName); }
pDSSearch->FreeColumn(&ADsPath); }
if (dwRet != ERROR_SUCCESS || hr != S_OK) goto error;
hr = pDSSearch->GetNextRow(hSearchHandle); BAIL_ON_FAILURE(hr); }
hr = S_OK;
error:
if (hr != S_OK) dwRet = ERROR_DS_UNAVAILABLE;
if (pDsRole) DsRoleFreeMemory((PVOID) pDsRole);
if (pDNR) DsFreeNameResult(pDNR);
if (hDS) DsUnBind(&hDS);
if (pDCI) NetApiBufferFree(pDCI);
if (hSearchHandle) pDSSearch->CloseSearchHandle(hSearchHandle);
if (pszUNCNameSearch) FreeSplMem(pszUNCNameSearch);
if (pDSSearch) pDSSearch->Release();
if (pszSearchRoot) FreeSplMem(pszSearchRoot);
return dwRet; }
DWORD MovePrintQueue( PCWSTR pszObjectGUID, PCWSTR pszNewContainer, // Container path
PCWSTR pszNewCN // Object CN
) { PWSTR pszCurrentContainer = NULL; PWSTR pszCurrentCN = NULL; HRESULT hr; IADsContainer *pADsContainer = NULL; IDispatch *pNewObject = NULL;
// Get PublishPoint from GUID
hr = GetPublishPointFromGUID(pszObjectGUID, &pszCurrentContainer, &pszCurrentCN); BAIL_ON_FAILURE(hr);
if (pszCurrentContainer) { // Get container
hr = ADsGetObject( pszCurrentContainer, IID_IADsContainer, (void **) &pADsContainer); BAIL_ON_FAILURE(hr);
// Move PrintQueue
if (wcscmp(pszCurrentContainer, pszNewContainer)) { hr = pADsContainer->MoveHere((PWSTR) pszNewContainer, (PWSTR) pszNewCN, &pNewObject); BAIL_ON_FAILURE(hr); } }
error:
if (pszCurrentContainer) FreeSplMem(pszCurrentContainer);
if (pszCurrentCN) FreeSplMem(pszCurrentCN);
if (pADsContainer) pADsContainer->Release();
if (pNewObject) pNewObject->Release();
return hr; }
HRESULT GetPublishPointFromGUID( PCWSTR pszObjectGUID, PWSTR *ppszDN, PWSTR *ppszCN ) { DWORD dwRet, nBytes, nChars; PWSTR pNames[2]; DS_NAME_RESULT *pDNR = NULL; DOMAIN_CONTROLLER_INFO *pDCI = NULL; HANDLE hDS = NULL; PWSTR psz; HRESULT hr = S_OK;
dwRet = Bind2DS(&hDS, &pDCI, DS_DIRECTORY_SERVICE_PREFERRED); if (dwRet != ERROR_SUCCESS) goto error;
// Get Publish Point
if (ppszDN) {
pNames[0] = (PWSTR) pszObjectGUID; pNames[1] = NULL;
if (!(DsCrackNames( hDS, DS_NAME_NO_FLAGS, DS_UNKNOWN_NAME, DS_FQDN_1779_NAME, 1, &pNames[0], &pDNR) == ERROR_SUCCESS)) {
dwRet = GetLastError(); goto error; }
if (pDNR->rItems[0].status != DS_NAME_NO_ERROR) { if (pDNR->rItems[0].status == DS_NAME_ERROR_RESOLVING) dwRet = ERROR_PATH_NOT_FOUND; else dwRet = pDNR->rItems[0].status;
goto error; }
// Separate DN into CN & PublishPoint
// pDNR has form: CN=CommonName,DN...
hr = FQDN2CNDN(pDCI->DomainControllerName + 2, pDNR->rItems[0].pName, ppszCN, ppszDN); BAIL_ON_FAILURE(hr); }
error:
if (pDNR) DsFreeNameResult(pDNR);
if (hDS) DsUnBind(&hDS);
if (pDCI) NetApiBufferFree(pDCI);
if (dwRet != ERROR_SUCCESS) { hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, dwRet); }
if (FAILED(hr)) { FreeSplMem(*ppszCN); FreeSplMem(*ppszDN); *ppszCN = *ppszDN = NULL; }
return hr; }
DWORD Bind2DS( HANDLE *phDS, DOMAIN_CONTROLLER_INFO **ppDCI, ULONG Flags ) { DWORD dwRet;
dwRet = DsGetDcName(NULL, NULL, NULL, NULL, Flags, ppDCI); if (dwRet == ERROR_SUCCESS) {
if ((*ppDCI)->Flags & DS_DS_FLAG) {
dwRet = DsBind (NULL, (*ppDCI)->DomainName, phDS); if (dwRet != ERROR_SUCCESS) {
NetApiBufferFree(*ppDCI); *ppDCI = NULL;
if (!(Flags & DS_FORCE_REDISCOVERY)) { dwRet = Bind2DS(phDS, ppDCI, DS_FORCE_REDISCOVERY | Flags); } } } else { NetApiBufferFree(*ppDCI); *ppDCI = NULL; dwRet = ERROR_CANT_ACCESS_DOMAIN_INFO; } }
return dwRet; }
HRESULT FQDN2CNDN( PWSTR pszDCName, PWSTR pszFQDN, PWSTR *ppszCN, PWSTR *ppszDN ) { IADs *pADs = NULL; PWSTR pszCN = NULL; PWSTR pszDN = NULL; PWSTR pszLDAPPath = NULL; HRESULT hr;
// Get LDAP path to object
hr = BuildLDAPPath(pszDCName, pszFQDN, &pszLDAPPath); BAIL_ON_FAILURE(hr);
// Get DN
hr = ADsGetObject(pszLDAPPath, IID_IADs, (void **) &pADs); BAIL_ON_FAILURE(hr);
hr = pADs->get_Parent(&pszDN); BAIL_ON_FAILURE(hr);
if (!(*ppszDN = AllocSplStr(pszDN))) { hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); BAIL_ON_FAILURE(hr); }
// Get CN
hr = pADs->get_Name(&pszCN); BAIL_ON_FAILURE(hr);
if (!(*ppszCN = AllocSplStr(pszCN))) { hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); BAIL_ON_FAILURE(hr); }
error:
if (pADs) pADs->Release();
if (pszCN) SysFreeString(pszCN);
if (pszDN) SysFreeString(pszDN);
FreeSplStr(pszLDAPPath);
if (FAILED(hr)) { FreeSplStr(*ppszCN); FreeSplStr(*ppszDN); }
return hr; }
HRESULT BuildLDAPPath( PWSTR pszDC, PWSTR pszFQDN, PWSTR *ppszLDAPPath ) { DWORD nBytes; HRESULT hr;
// LDAP:// + pDCName + / + pName + 1
nBytes = (wcslen(pszDC) + wcslen(pszFQDN) + 9)*sizeof(WCHAR);
if (!(*ppszLDAPPath = (PWSTR) AllocSplMem(nBytes))) { hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); BAIL_ON_FAILURE(hr); }
hr = StringCbPrintf(*ppszLDAPPath, nBytes, L"LDAP://%ws/%ws", pszDC,pszFQDN);
error:
return hr; }
DWORD UNC2Printer( PCWSTR pszUNC, PWSTR *ppszPrinter ) { PWSTR psz; if (!pszUNC || pszUNC[0] != L'\\' || pszUNC[1] != L'\\') return ERROR_INVALID_PARAMETER;
if(!(psz = wcsrchr(pszUNC + 2, L'\\'))) return ERROR_INVALID_PARAMETER;
if (!(*ppszPrinter = (PWSTR) AllocSplStr(psz + 1))) return GetLastError();
return ERROR_SUCCESS; }
DWORD UNC2Server( PCWSTR pszUNC, PWSTR *ppszServer ) { PWSTR psz; DWORD cb; DWORD nChars;
if (!pszUNC || pszUNC[0] != L'\\' || pszUNC[1] != L'\\') return ERROR_INVALID_PARAMETER;
if(!(psz = wcschr(pszUNC + 2, L'\\'))) return ERROR_INVALID_PARAMETER;
cb = (DWORD) ((ULONG_PTR) psz - (ULONG_PTR) pszUNC + sizeof *psz);
if (!(*ppszServer = (PWSTR) AllocSplMem(cb))) return GetLastError();
nChars = (DWORD) (psz - pszUNC); wcsncpy(*ppszServer, pszUNC, nChars); (*ppszServer)[nChars] = L'\0';
return ERROR_SUCCESS; }
// Utility routine to report if a printer is color or monochrome
BOOL ThisIsAColorPrinter( LPCTSTR lpstrName ) { HANDLE hPrinter = NULL; LPTSTR lpstrMe = const_cast <LPTSTR> (lpstrName); BOOL bReturn = FALSE; LPDEVMODE lpdm = NULL; long lcbNeeded;
if (!OpenPrinter(lpstrMe, &hPrinter, NULL)) { goto error; }
// First, use DocumentProperties to find the correct DEVMODE size- we
// must use the DEVMODE to force color on, in case the user's defaults
// have turned it off...
lcbNeeded = DocumentProperties(NULL, hPrinter, lpstrMe, NULL, NULL, 0); if (lcbNeeded <= 0) { goto error; }
lpdm = (LPDEVMODE) AllocSplMem(lcbNeeded); if (lpdm) {
lpdm->dmSize = sizeof(DEVMODE); lpdm->dmFields = DM_COLOR; lpdm->dmColor = DMCOLOR_COLOR;
if (IDOK == DocumentProperties(NULL, hPrinter, lpstrMe, lpdm, lpdm, DM_IN_BUFFER | DM_OUT_BUFFER)) {
// Finally, we can create the DC!
HDC hdcThis = CreateDC(NULL, lpstrName, NULL, lpdm);
if (hdcThis) { bReturn = 2 < (unsigned) GetDeviceCaps(hdcThis, NUMCOLORS); DeleteDC(hdcThis); } } }
error:
FreeSplMem(lpdm);
if (hPrinter) ClosePrinter(hPrinter);
return bReturn; }
HRESULT DeleteDSObject( PWSTR pszADsPath ) { BSTR bstrCommonName = NULL; PWSTR pszParent = NULL; PWSTR pszCN = NULL; PWSTR pszLDAPPath = NULL; IADs *pADs = NULL; IADsContainer *pContainer = NULL; DWORD cch; HRESULT hr; DWORD nSize;
if(pszADsPath && !_wcsnicmp(pszADsPath , L"GC://" , 5)){
//
// Build LDAP://..... path from GC://.... path
// 3 comes from len(LDAP) - len(GC) + len(string_terminator)
//
nSize = (wcslen(pszADsPath) + 3)* sizeof(WCHAR); if (!(pszLDAPPath = (PWSTR) AllocSplMem(nSize))) { hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); goto error; } if (FAILED(hr = StringCbPrintf(pszLDAPPath, nSize, L"LDAP%ws", pszADsPath + 2))) { goto error; } }
// Get PrintQueue object
hr = ADsGetObject(pszLDAPPath, IID_IADs, (void **) &pADs); BAIL_ON_FAILURE(hr);
// Get the CommonName & don't forget the "CN="
hr = get_BSTR_Property(pADs, L"cn", &bstrCommonName); BAIL_ON_FAILURE(hr);
cch = (SysStringLen(bstrCommonName) + 4);
if (!(pszCN = (PWSTR) AllocSplMem(cch * sizeof(WCHAR)))) { hr = dw2hr(GetLastError()); BAIL_ON_FAILURE(hr); }
StrNCatBuff(pszCN, cch, L"CN=", bstrCommonName, NULL);
// Get the Parent ADsPath
hr = pADs->get_Parent(&pszParent); BAIL_ON_FAILURE(hr);
// Get the Parent object
hr = ADsGetObject( pszParent, IID_IADsContainer, (void **) &pContainer); BAIL_ON_FAILURE(hr);
// Delete the printqueue
hr = pContainer->Delete(SPLDS_PRINTER_CLASS, pszCN);
error:
if (pADs) pADs->Release();
if (pContainer) pContainer->Release();
if (bstrCommonName) SysFreeString(bstrCommonName);
if (pszParent) SysFreeString(pszParent);
if (pszCN) FreeSplMem(pszCN);
if(pszLDAPPath) FreeSplMem(pszLDAPPath);
return hr; }
DWORD GetCommonName( HANDLE hPrinter, PWSTR *ppszCommonName ) { DWORD nBytes; PWSTR psz; PPRINTER_INFO_2 pInfo2 = NULL; DWORD cbNeeded; DWORD dwRet; PWSTR pszServerName, pszPrinterName;
// Get Server & Share names
if (!GetPrinter(hPrinter, 2, (PBYTE) pInfo2, 0, &cbNeeded)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { dwRet = GetLastError(); goto error; }
if (!(pInfo2 = (PPRINTER_INFO_2) AllocSplMem(cbNeeded))) { dwRet = GetLastError(); goto error; }
if (!GetPrinter(hPrinter, 2, (PBYTE) pInfo2, cbNeeded, &cbNeeded)) { dwRet = GetLastError(); goto error; } pszServerName = pInfo2->pServerName; if (!pszServerName) { DBGMSG(DBG_ERROR,("GetPrinter returned NULL ServerName")); dwRet = ERROR_INVALID_DATA; goto error; }
pszPrinterName = pInfo2->pShareName ? pInfo2->pShareName : pInfo2->pPrinterName;
} else { // We should never get here. If we do, something is wrong
// with the server and we have no meaningful error to report,
// so just claim invalid data.
DBGMSG(DBG_ERROR,("INVALID GetPrinter return")); dwRet = ERROR_INVALID_DATA; goto error; }
// "CN=Server-Printer"
nBytes = (wcslen(pszPrinterName) + wcslen(pszServerName) + 5)*sizeof(WCHAR); if (!(*ppszCommonName = psz = (PWSTR) AllocSplMem(nBytes))) { dwRet = GetLastError(); goto error; }
// CN=
StringCbCopy(psz, nBytes, L"CN=");
// Server
for(psz += 3, pszServerName += 2 ; *pszServerName ; ++psz, ++pszServerName) { *psz = wcschr(DN_SPECIAL_CHARS, *pszServerName) ? TEXT('_') : *pszServerName; } *psz = L'-';
// Printer
for(++psz; *pszPrinterName ; ++psz, ++pszPrinterName) { *psz = wcschr(DN_SPECIAL_CHARS, *pszPrinterName) ? TEXT('_') : *pszPrinterName; }
// NULL
*psz = *pszPrinterName;
// DS only allows 64 characters in CN attribute, so shorten this if needed
if (wcslen(pszPrinterName) > 62) pszPrinterName[63] = NULL;
error:
FreeSplMem(pInfo2);
return ERROR_SUCCESS; }
PWSTR AllocGlobalStr( PWSTR pszIn ) { DWORD cb; PWSTR pszOut = NULL;
if (!pszIn) return NULL;
cb = (wcslen(pszIn) + 1)*sizeof *pszIn;
if (pszOut = (PWSTR) GlobalAlloc(GMEM_FIXED, cb)) { StringCbCopy(pszOut, cb, pszIn); }
return pszOut; }
VOID FreeGlobalStr( PWSTR pszIn ) { if (pszIn) GlobalFree(pszIn); }
DWORD GetADsPathFromGUID( PCWSTR pszObjectGUID, PWSTR *ppszDN ) { DWORD dwRet, nBytes, nChars; PWSTR pNames[2]; DS_NAME_RESULT *pDNR = NULL; DOMAIN_CONTROLLER_INFO *pDCI = NULL; HANDLE hDS = NULL; PWSTR psz;
dwRet = Bind2DS(&hDS, &pDCI, DS_DIRECTORY_SERVICE_PREFERRED); if (dwRet != ERROR_SUCCESS) goto error;
// Get Publish Point
if (ppszDN) {
pNames[0] = (PWSTR) pszObjectGUID; pNames[1] = NULL;
if (!(DsCrackNames( hDS, DS_NAME_NO_FLAGS, DS_UNKNOWN_NAME, DS_FQDN_1779_NAME, 1, &pNames[0], &pDNR) == ERROR_SUCCESS)) {
dwRet = GetLastError(); goto error; }
if (pDNR->rItems[0].status != DS_NAME_NO_ERROR) { if (pDNR->rItems[0].status == DS_NAME_ERROR_RESOLVING) dwRet = ERROR_PATH_NOT_FOUND; else dwRet = pDNR->rItems[0].status;
goto error; }
// LDAP:// + pDCName + / + pName + 1
nBytes = (wcslen(pDCI->DomainControllerName + 2) + wcslen(pDNR->rItems[0].pName) + 9)*sizeof(WCHAR);
if (!(*ppszDN = (PWSTR) AllocSplMem(nBytes))) { dwRet = GetLastError(); goto error; }
StringCbPrintf(*ppszDN, nBytes, L"LDAP://%ws/%ws", pDCI->DomainControllerName + 2,pDNR->rItems[0].pName); }
error:
if (pDNR) DsFreeNameResult(pDNR);
if (hDS) DsUnBind(&hDS);
if (pDCI) NetApiBufferFree(pDCI);
if (dwRet != ERROR_SUCCESS) { FreeSplMem(*ppszDN); *ppszDN = NULL; }
return dwRet; }
PWSTR GetDNWithServer( PCWSTR pszDNIn ) { DOMAIN_CONTROLLER_INFO *pDCI = NULL; DWORD nBytes; PWSTR pszDNOut = NULL; DWORD dwRet;
// Convert pszDNIn into a DN with the DC name, if it isn't already there
// Check for existing DC name or badly formed name
if (wcsncmp(pszDNIn, L"LDAP://", 7) || wcschr(pszDNIn + 7, L'/')) goto error;
// Get DC name
dwRet = DsGetDcName(NULL, NULL, NULL, NULL, 0, &pDCI); if (dwRet != ERROR_SUCCESS) { goto error; }
// Build name
// LDAP:// + pDCName + / + pName + 1
nBytes = (wcslen(pDCI->DomainControllerName + 2) + wcslen(pszDNIn + 7) + 9)*sizeof(WCHAR);
if (!(pszDNOut = (PWSTR) AllocSplMem(nBytes))) goto error;
StringCbPrintf(pszDNOut, nBytes, L"LDAP://%ws/%ws", pDCI->DomainControllerName + 2, pszDNIn + 7);
error:
if (pDCI) NetApiBufferFree(pDCI);
return pszDNOut; }
DWORD hr2dw( HRESULT hr ) { if (SUCCEEDED(hr)) return ERROR_SUCCESS;
if (HRESULT_FACILITY(hr) == FACILITY_WIN32) return HRESULT_CODE(hr);
if (hr != HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS)) return ERROR_DS_UNAVAILABLE;
return hr; }
PWSTR DelimString2MultiSz( PWSTR pszIn, WCHAR wcDelim ) { DWORD cb; PWSTR pszOut = NULL;
// pszIn looks like L"xxx,xxxx,xxx,xxx"
// the output looks like L"xxx0xxxx0xxx0xxx00"
// Replace all wcDelim characters with NULLs & add a NULL
if (!pszIn || !*pszIn) return NULL;
cb = (wcslen(pszIn) + 2)*sizeof *pszIn;
pszOut = (PWSTR) AllocSplMem(cb);
if (pszOut) {
DWORD i;
for (i = 0 ; pszIn[i] ; ++i) { pszOut[i] = (pszIn[i] == wcDelim) ? L'\0' : pszIn[i]; } pszOut[i] = pszOut[i + 1] = L'\0'; }
return pszOut; }
HRESULT GetPrinterInfo2( HANDLE hPrinter, PPRINTER_INFO_2 *ppInfo2 ) { HRESULT hr = S_OK; DWORD cbNeeded;
// Get PRINTER_INFO_2 properties
if (!GetPrinter(hPrinter, 2, (PBYTE) *ppInfo2, 0, &cbNeeded)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { hr = dw2hr(GetLastError()); goto error; }
if (!(*ppInfo2 = (PPRINTER_INFO_2) AllocSplMem(cbNeeded))) { hr = dw2hr(GetLastError()); goto error; } if (!GetPrinter(hPrinter, 2, (PBYTE) *ppInfo2, cbNeeded, &cbNeeded)) { hr = dw2hr(GetLastError()); goto error; } }
error: return hr; }
DWORD FQDN2Canonical( PWSTR pszIn, PWSTR *ppszOut ) { DWORD dwRet = ERROR_SUCCESS; DS_NAME_RESULT *pDNR = NULL; PWSTR pNames[2]; *ppszOut = NULL;
if (wcslen(pszIn) < 8) { dwRet = ERROR_INVALID_PARAMETER; goto error; }
pNames[0] = pszIn + 7; // Input string is LDAP://CN=... Strip off the LDAP:// portion
pNames[1] = NULL;
if (!(DsCrackNames( INVALID_HANDLE_VALUE, DS_NAME_FLAG_SYNTACTICAL_ONLY, DS_FQDN_1779_NAME, DS_CANONICAL_NAME, 1, &pNames[0], &pDNR) == ERROR_SUCCESS)) {
dwRet = GetLastError(); goto error; }
if (pDNR->rItems[0].status != DS_NAME_NO_ERROR) { if (pDNR->rItems[0].status == DS_NAME_ERROR_RESOLVING) dwRet = ERROR_PATH_NOT_FOUND; else dwRet = pDNR->rItems[0].status;
goto error; }
if (!(*ppszOut = AllocSplStr(pDNR->rItems[0].pName))) { dwRet = ERROR_NOT_ENOUGH_MEMORY; } error:
if (pDNR) DsFreeNameResult(pDNR);
return dwRet; }
BOOL DevCapMultiSz( PWSTR pszUNCName, IADs *pPrintQueue, WORD fwCapability, DWORD dwElementBytes, PWSTR pszAttributeName ) { DWORD dwResult, cbBytes; PWSTR pszDevCapBuffer = NULL; PWSTR pszRegData = NULL; HRESULT hr;
_try { dwResult = DeviceCapabilities( pszUNCName, NULL, fwCapability, NULL, NULL);
if (dwResult != GDI_ERROR) { pszDevCapBuffer = (PWSTR) AllocSplMem(dwResult*dwElementBytes*sizeof(WCHAR));
if (pszDevCapBuffer) { dwResult = DeviceCapabilities( pszUNCName, NULL, fwCapability, pszDevCapBuffer, NULL);
if (dwResult != GDI_ERROR) { if (!(pszRegData = DevCapStrings2MultiSz(pszDevCapBuffer, dwResult, dwElementBytes, &cbBytes))) { dwResult = GDI_ERROR; } } } else { dwResult = GDI_ERROR; } } } _except(1) { SetLastError(GetExceptionCode()); dwResult = GDI_ERROR; }
if (dwResult != GDI_ERROR) {
hr = PublishDsData( pPrintQueue, pszAttributeName, REG_MULTI_SZ, (PBYTE) pszRegData);
if (FAILED(hr)) { SetLastError(HRESULT_CODE(hr)); dwResult = GDI_ERROR; } }
FreeSplStr(pszDevCapBuffer); FreeSplStr(pszRegData); return dwResult != GDI_ERROR; }
PWSTR DevCapStrings2MultiSz( PWSTR pszDevCapString, DWORD nDevCapStrings, DWORD dwDevCapStringLength, DWORD *pcbBytes ) { DWORD i, cbBytes, cbSize; PWSTR pszMultiSz = NULL; PWSTR pStr;
if (!pszDevCapString || !pcbBytes) return NULL;
*pcbBytes = 0;
//
// Devcap buffers may not be NULL terminated
//
cbBytes = (nDevCapStrings*(dwDevCapStringLength + 1) + 1)*sizeof(WCHAR);
//
// Allocate and copy
//
if (pszMultiSz = (PWSTR) AllocSplMem(cbBytes)) { for(i = 0, pStr = pszMultiSz, cbBytes = 0 ; i < nDevCapStrings ; ++i, pStr += cbSize, cbBytes +=cbSize ) { wcsncpy(pStr, pszDevCapString + i*dwDevCapStringLength, dwDevCapStringLength); cbSize = *pStr ? wcslen(pStr) + 1 : 0; } *pStr = L'\0'; *pcbBytes = (cbBytes + 1) * sizeof(WCHAR); }
return pszMultiSz; }
HRESULT MachineIsInMyForest( PWSTR pszMachineName ) { DWORD dwRet; HRESULT hr; PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pMachineRole = NULL; PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pMyRole = NULL;
dwRet = DsRoleGetPrimaryDomainInformation( pszMachineName, DsRolePrimaryDomainInfoBasic, (PBYTE *) &pMachineRole); if (dwRet != ERROR_SUCCESS) { hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, dwRet); goto error; }
dwRet = DsRoleGetPrimaryDomainInformation( NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *) &pMyRole); if (dwRet != ERROR_SUCCESS) { hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, dwRet); goto error; }
dwRet = DnsNameCompare_W(pMachineRole->DomainForestName, pMyRole->DomainForestName); hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_WIN32, dwRet);
error:
if (pMachineRole) DsRoleFreeMemory((PVOID) pMachineRole);
if (pMyRole) DsRoleFreeMemory((PVOID) pMyRole);
return hr; }
|